mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-07 08:33:50 +08:00
Generic arrow properties and generic methods now have an erased runtime value, their instance with every type parameter bound to unknown. Calls through a round trip via any, a function result, an array element or a class-backed interface call that value and convert the result to the call's type, as JavaScript does. Direct calls on a known definition keep their monomorphized path. Fixes #905 Co-authored-by: Konstantin Mikheev <8560582+konmik@users.noreply.github.com>
54 lines
2.0 KiB
TypeScript
54 lines
2.0 KiB
TypeScript
// Generic function VALUE fences, named: every shape here keeps the generic
|
|
// signature alive where static monomorphization cannot follow.
|
|
|
|
// A reassigned binding cannot resolve statically — a later write could hold
|
|
// a structurally identical function with a different body.
|
|
let flip = <T>(x: T): T => x;
|
|
flip = <T>(x: T): T => x;
|
|
console.log(flip(1));
|
|
|
|
// An ALIAS binding registers its target (calls through it monomorphize),
|
|
// but a USE with no pinning context still keeps the generic signature —
|
|
// the value fences at the reference, not the binding.
|
|
const id = <T>(x: T): T => x;
|
|
const stored = id;
|
|
console.log(typeof stored);
|
|
|
|
// An alias of a REASSIGNED binding never registers: the target's own
|
|
// fence reports, and the alias falls back to the ordinary binding story.
|
|
const flipAlias = flip;
|
|
console.log(flipAlias(5));
|
|
|
|
// Declared inside a function: instances are module functions and cannot
|
|
// capture the enclosing frame.
|
|
function outer(): number {
|
|
const inner = <T>(x: T): T => x;
|
|
return inner(3);
|
|
}
|
|
console.log(outer());
|
|
|
|
// An ambient binding of generic function type now compiles to Node's exact
|
|
// ReferenceError at the access (the declare-erasure stance — no diagnostic
|
|
// here; the optional chain cannot guard the root's own throw).
|
|
declare const ambient: undefined | (<T>(f: (a: T) => T) => T);
|
|
console.log(ambient?.((n: number) => n) === undefined);
|
|
|
|
// A call whose RESULT is itself a generic function: the returned signature
|
|
// keeps its type parameters and would need the producing call's frame.
|
|
const curried = <T>(x: T) => <U>(y: U): string => `${x}|${y}`;
|
|
console.log(curried(1)("a"));
|
|
|
|
// Ambient `declare class` generic methods are signature-only. Through an
|
|
// AMBIENT-ROOTED receiver the call now compiles to Node's ReferenceError
|
|
// at the root (the declare-const chain stance — no diagnostic here); a
|
|
// receiver that exists at runtime keeps the fence.
|
|
declare class Amb {
|
|
m<T>(x: T): T;
|
|
}
|
|
declare const amb: Amb;
|
|
console.log(amb.m(4));
|
|
function throughParam(a: Amb): void {
|
|
console.log(a.m(4));
|
|
}
|
|
throughParam(amb);
|