TypeScript泛型异常:为何部分类调用get函数类型推导错误?
修复TypeScript泛型推断歧义问题
你的问题出在GenericToken<T>联合类型的泛型推断歧义上。当传入带有成员的类时,TypeScript无法正确将构造函数匹配到Newable<T>分支,导致泛型参数T被错误推断为string(这是TypeScript推断时的歧义优先匹配问题)。
以下两种方法可以解决这个问题:
方案一:使用函数重载明确类型匹配
通过为get函数添加重载,明确不同参数类型对应的泛型推断逻辑,避免联合类型带来的歧义:
class Token<T> { public name: T; constructor(name: T) { this.name = name; } } class LazyToken<T> { public callback: () => GenericToken<T>; constructor(callback: () => GenericToken<T>) { this.callback = callback; } public resolve() { return this.callback(); } } type GenericToken<T = unknown> = Token<T> | LazyToken<T> | Newable<T>; type Newable< TInstance = unknown, TArgs extends unknown[] = any[] > = new (...args: TArgs) => TInstance; // 添加函数重载 function get<T>(token: Token<T>): T | undefined; function get<T>(token: LazyToken<T>): T | undefined; function get<T>(token: Newable<T>): T | undefined; function get<T>(token: GenericToken<T>, options: any = {}): T | undefined { return 123 as T; } class Test1 { } class Test2 { public name = 123; } class Test3 { sayHello() { } } class Test4 { public hello = 123; } class Test5 { public hello = 123; sayHello() { } } const test1 = get(Test1); // Test1 | undefined const test2 = get(Test2); // Test2 | undefined const test3 = get(Test3); // Test3 | undefined const test4 = get(Test4); // Test4 | undefined const test5 = get(Test5); // Test5 | undefined
方案二:使用条件类型提取正确的返回类型
通过条件类型ExtractTokenType,从传入的GenericToken中提取对应的实例类型,替代直接依赖泛型推断:
class Token<T> { public name: T; constructor(name: T) { this.name = name; } } class LazyToken<T> { public callback: () => GenericToken<T>; constructor(callback: () => GenericToken<T>) { this.callback = callback; } public resolve() { return this.callback(); } } type Newable< TInstance = unknown, TArgs extends unknown[] = any[] > = new (...args: TArgs) => TInstance; type GenericToken<T = unknown> = Token<T> | LazyToken<T> | Newable<T>; // 定义条件类型提取目标类型 type ExtractTokenType<T> = T extends Token<infer U> ? U : T extends LazyToken<infer U> ? U : T extends Newable<infer U> ? U : unknown; function get<T extends GenericToken<any>>(token: T, options: any = {}): ExtractTokenType<T> | undefined { return 123 as ExtractTokenType<T>; } class Test1 { } class Test2 { public name = 123; } class Test3 { sayHello() { } } class Test4 { public hello = 123; } class Test5 { public hello = 123; sayHello() { } } const test1 = get(Test1); // Test1 | undefined const test2 = get(Test2); // Test2 | undefined const test3 = get(Test3); // Test3 | undefined const test4 = get(Test4); // Test4 | undefined const test5 = get(Test5); // Test5 | undefined
两种方案都能解决你的问题,方案一更直观,适合类型分支明确的场景;方案二更灵活,适合复杂的类型提取场景。
内容的提问来源于stack exchange,提问作者threetree
相关产品推荐
相关产品推荐

