TS => MJS. Iteration 2 - #1453
Conversation
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
functionalscript | 15c90ec | Commit Preview URL Branch Preview URL |
Aug 08 2026, 12:21 AM |
o2alexanderfedin
left a comment
There was a problem hiding this comment.
Approving at acb29736. Three modules converted — types/function, types/nullable, types/option — plus ~45 mechanical import rewrites. The generics here are much richer than #1452's asserts, so I checked that the JSDoc @type annotations are actually enforced rather than silently collapsing to any, which is the failure mode that would keep the suite green while deleting the type safety.
Contracts hold. A probe exercising compose / identity / flip / fn / map / unwrap / fromUndefined / mapUnwrap compiles clean, and six deliberately-wrong uses each produce the correct specific error:
| mutation | diagnostic |
|---|---|
identity(1) as string |
TS2322 number → string |
compose(g)((s: number) => s) |
TS2345 not assignable to Func<string, number> |
unwrap(…) as string |
TS2322 number → string |
fn(g).map(…).result('nope') |
TS2345 string → number |
flip(…)(1) |
TS2345 number → string |
map(…)(…) as number |
TS2322 Nullable<string> → number |
Func<string, number> and Nullable<string> appearing in those messages is the useful part — the typedefs resolve, they aren't any. compose's two separate generic scopes survive too: compose(g) stays generic in O and instantiates independently at each call.
npm test → pass: 2354, fail: 0, total: 2354, identical to main. npx tsc clean.
One observation: Fn changes from private to public
In the old module.f.ts, Fn was deliberately declared without export:
type Fn<I, O> = { ... } // no exportA JSDoc @typedef in a module is exported whether you want it or not, so it's now importable. Confirmed in both directions:
- on
main:import type { Fn } from './module.f.ts'→TS2724: '"./module.f.ts"' has no exported member named 'Fn' - on this branch: the same import against
module.f.mjscompiles clean
I also tried /** @private */ on the typedef to see whether the old visibility could be preserved — it does not suppress the export, so there's no cheap fix; the alternatives are to accept the widening or restructure.
Not blocking, and arguably harmless: Fn is only referenced inside its own module, and it's a benign utility type. But #1449's plan sets the bar at "translate without changing the public type contract", and this is a real (if small) contract change in the widening direction, so it seems worth a conscious decision rather than passing unnoticed — especially since the same thing will recur for every unexported type the migration touches. Might be worth one line in the migration doc stating that unexported type aliases become public and that's accepted.
No description provided.