You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 01:54:50