mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-08 08:44:37 +08:00
- A call that resolves to an overload signature of a generic function or
method with an implementation (`load<T>(k, map: Mapper<T>): Promise<T>;
load(k): Promise<Reply>; load<T>(k, map?) {...}`) monomorphizes the
implementation under the bindings the overload's resolved signature
proves; a type parameter the overload never mentions is unknown, and
parameters the overload omits must be optional in the implementation.
It was refused.
- `view.m(...)` where `view` is a `Pick`/`Omit` view of a program class
and `m` is a generic (or generically overloaded) method extracts the
instance from the view's live receiver and calls the method statically,
instead of a runtime refusal reading the method through the untyped
view.
- Binding inference pairs the arms of `T | Promise<T>` with an
instantiated `R | Promise<R>`, and `unknown | Promise<unknown>` maps to
the checked-dynamic value the checker reduces it to.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
55 lines
1.8 KiB
TypeScript
55 lines
1.8 KiB
TypeScript
// Calls that resolve to OVERLOAD signatures of a generic method or
|
|
// function: the implementation monomorphizes under what the overload
|
|
// proves for its type parameters (a parameter the overload never mentions
|
|
// is unknown), directly and through a `Pick` view of the class, whose
|
|
// live receiver keeps the instance's state. `T | Promise<T>` callbacks
|
|
// bind T from either arm.
|
|
interface Reply {
|
|
code: number;
|
|
text: string;
|
|
}
|
|
type Mapper<T> = (reply: Reply) => T | Promise<T>;
|
|
|
|
class Store {
|
|
loads = 0;
|
|
async load<T>(key: string, map: Mapper<T>): Promise<T>;
|
|
async load(key: string): Promise<Reply>;
|
|
async load<T>(key: string, map?: Mapper<T>): Promise<T | Reply> {
|
|
this.loads++;
|
|
const reply: Reply = { code: 200, text: key };
|
|
if (map === undefined) return reply;
|
|
return await map(reply);
|
|
}
|
|
}
|
|
|
|
interface Services {
|
|
store: Pick<Store, "load">;
|
|
}
|
|
|
|
function pick<T>(items: T[], index: number): T;
|
|
function pick<T>(items: T[]): T;
|
|
function pick<T>(items: T[], index = 0): T {
|
|
return items[index]!;
|
|
}
|
|
|
|
async function settle<T>(reply: Reply, map?: Mapper<T>): Promise<T | Reply> {
|
|
return map ? await map(reply) : reply;
|
|
}
|
|
|
|
async function main(): Promise<void> {
|
|
const store = new Store();
|
|
const plain = await store.load("alpha");
|
|
console.log(plain.code, plain.text);
|
|
const length = await store.load("beta", (reply) => reply.text.length);
|
|
console.log(length * 2);
|
|
const services: Services = { store };
|
|
const viaView = await services.store.load("gamma");
|
|
const upper = await services.store.load("delta", async (reply) => reply.text.toUpperCase());
|
|
console.log(viaView.text, upper, store.loads);
|
|
console.log(pick(["x", "y"]), pick([1, 2, 3], 2));
|
|
console.log(JSON.stringify(await settle<Reply>({ code: 1, text: "s" })));
|
|
console.log(await settle({ code: 2, text: "tt" }, (reply) => reply.code + reply.text.length));
|
|
}
|
|
|
|
main();
|