在第一个示例中,编译器在创建类Foo的新对象时不会出现错误.

class Foo<Options extends number[] = (1 | 2 | 3)[] > {
  constructor(
    public options: Options,
    public option: Options[number]
  ) {}
}

new Foo([4, 5], 1);

如果我现在在Options之前添加另一个类型参数,然后为前面的类型参数传递一个类型,编译器正确地报告(screenshot of the error).

class Foo<Unused, Options extends number[] = (1 | 2 | 3)[] > {
  constructor(
    public options: Options,
    public option: Options[number]
  ) {}
}

new Foo<any>([4, 5], 1);

我希望第一个示例与第二个示例的行为相同.在第二个示例中,编译器正确地报告第一个传递的构造函数参数不能赋给默认的Options类型(1 | 2 | 3)[].为什么仅仅将any作为Unused类型参数传递就会突然产生所需的行为?为什么它不能像第一个示例中预期的那样工作?

推荐答案

调用/构造generic函数/类有两种方法.您可以使用<>语法显式指定类型参数,如foo<X>(x)new Foo<X>(x)bar<X, Y>(z);也可以省略类型参数,如foo(x)new Foo(x)bar(z),而不使用<>.

如果显式指定任何类型参数,则将使用这些参数.如果某些类型参数有default type arguments,而您省略了类型参数,则将使用缺省值.

另一方面,如果不指定任何类型参数,则所有类型参数将为inferred.在这种情况下将使用缺省值not(除非推断完全失败).

您可能希望能够"混合和匹配"此功能,指定一些类型参数,同时推断其他一些参数,或者获得缺省值而不是推断,但这目前是不可能的.在microsoft/TypeScript#26242岁的时候,有一个长期开放的GitHub要求这样的能力,但现在它不是语言的一部分.


考虑到这一点,我们可以解释你所看到的行为.首先:

class Foo<Options extends number[] = (1 | 2 | 3)[] > {
  constructor(
    public options: Options,
    public option: Options[number]
  ) {}
}

new Foo([4, 5], 1);

您尚未为Options指定generic类型参数. 没有< - >. 所以你得到了推论. Options是从options的自变量[4, 5]推断出来的,它被推断为number[]. (这个问题超出了范围,无法解释为什么它是number[],而不是(4 | 5)[][4, 5]或其他任何东西.

下一步:

 class Foo<Unused, Options extends number[] = (1 | 2 | 3)[] > {
  constructor(
    public options: Options,
    public option: Options[number]
  ) {}
}

new Foo<any>([4, 5], 1);

您已为Unused类型参数指定了any,因此不会发生任何推断.Options类型参数采用其默认类型(1 | 2 | 3)[],因此您会得到一个错误,因为[4, 5]不能赋给(1 | 2 | 3)[].


这些行为是否算作"期望的行为"取决于用例,但根据一些 comments ,这似乎不是真正需要的,而推理与缺省的问题掩盖了这一点.

Playground link to code

Typescript相关问答推荐

根据另一个成员推断类成员的类型

如何在方法中定义TypeScript返回类型,以根据参数化类型推断变量的存在?

typescribe不能使用值来索引对象类型,该对象类型满足具有该值的另一个类型'

为什么TypeScript失go 了类型推断,默认为any?''

如何在typescript中设置对象分配时的键类型和值类型

编剧错误:正在等待Expect(Locator).toBeVisible()

错误TS2403:后续变量声明必须具有相同的类型.变量';CRYPTO';的类型必须是';CRYPATO';,但这里的类型是';CRYPATO';

如何在react组件中使用doctype和html标签?

在排版修饰器中推断方法响应类型

下载量怎么会超过下载量?

在VSCode中显示eslint错误,但在终端中运行eslint命令时不显示?(Vite,React,TypeScript)

确保对象列表在编译时在类型脚本中具有唯一键

跟踪深度路径时按条件提取嵌套类型

如何通过属性名在两个泛型数组中找到匹配的对象?

如何在Nextjs路由处理程序中指定响应正文的类型

Rxjs将省略的可观测对象合并到一个数组中

将类型脚本函数返回类型提取到VSCode中的接口

使用强制转换编写打字函数的惯用方法

如何在TypeScrip中使用数组作为字符串的封闭列表?

如何正确键入泛型相对记录值类型?