【问题标题】:Typescript omit generic parameter when not needed打字稿在不需要时省略通用参数
【发布时间】:2022-12-01 02:25:41
【问题描述】:

我创建了一个带有返回参数的泛型函数类型,它完全依赖于输入参数类型,并且泛型参数有一个 extends 子句。这是一个虚拟版本:

type Foo = {}
type MyFunc <T extends Foo> = (a: T, b: T) => T[];

const bar: MyFunc<number> = (a: number, b: number) => [a,b];
const baz: MyFunc<boolean> = (a: boolean, b: boolean) => [a,b];

我正在使用通用参数来确保 1) ab 扩展 Foo 和 2) ab 是同一类型。

我遇到的问题是将 MyFunc 作为参数类型。我不需要 T 的确切类型;我只需要确保在调用时满足参数约束即可。例如,我想执行以下操作:

const makeArray = (qux: MyFunc) => qux(1,2);

12 属于同一类型,并且都扩展了 Foo,所以我知道函数调用会起作用,我会返回一个 number[]。但是,上面没有编译。打字稿说:

Generic type 'MyFunc' requires 1 type argument(s)

如果我使用(qux: MyFunc&lt;any&gt;),则根本不会进行类型检查。

是否有任何其他语法可以用来告诉 TypeScript 检查输入参数但不需要提前指定确切的类型?

【问题讨论】:

  • 如果 TypeScript 不知道确切的类型,它怎么知道如何检查输入参数?
  • 在调用点,它可以简单地检查 a 和 b 是否是同一类型并且它们都实现了 Foo。这足以使其类型安全,对吧?或者你能看到这样的情况是不合理的吗?
  • 那么你真的只是要求默认的通用参数吗? type MyFunc&lt;T extends Foo = Foo&gt;
  • 您可能也想使 makeArray 成为通用类型,并将此通用类型传递给 MyFunc,如 const makeArray = &lt;T extends Foo&gt;(qux: MyFunc&lt;T&gt;) =&gt; qux(1,2)
  • 这看起来像是对泛型类型参数范围的混淆。也许您正在寻找类似 @​​987654321@ 的内容,其中 qux 的类型实际上是通用的。如果那不是你要找的东西,你能准确地说出你的意思吗?

标签: typescript generics


【解决方案1】:

看起来你的泛型类型参数的范围是错误的。 TypeScript 中的泛型有两种截然不同(但相关)的“风格”。例如,参见TypeScript how to create a generic type alias for a generic function?typescript difference between placement of generics arguments

有通用的类型,其中类型参数是在类型名称本身上声明的,例如

// type GenType<T> = ...T...

还有通用的功能,其中类型参数声明在调用签名, 喜欢

// type GenFunc = <T>(...T...)=>...

您最初将 MyFunc 作为计算为非泛型函数的泛型类型

// original
type MyFunc<T extends Foo> = (a: T, b: T) => T[];

但这似乎不是你想要的。相反,您应该使它成为一个计算为通用函数的非通用类型:

// changed
type MyFunc = <T extends Foo>(a: T, b: T) => T[];

所以现在你可以创建一个类型为MyFunc的函数,对于每一个可能的T,它都会像你以前的MyFunc&lt;T&gt;一样工作:

// actually generic
const foo: MyFunc = (a, b) => [a, b];

如果你真的想限制这个函数,让它接受一些特定类型的参数,你可以使用instantiation expressions

const bar = foo<number>; 
// const bar: (a: number, b: number) => number[]
const baz = foo<boolean>; 
// const baz: (a: boolean, b: boolean) => boolean[]

但我不知道这有什么用。


无论如何,现在你可以按照你想要的方式实现makeArray,其中MyFunc不需要类型参数:

const makeArray = (qux: MyFunc) => qux(1, 2);
// const makeArray: (qux: MyFunc) => number[]

看,编译器推断出 makeArray 的返回类型是 number[],正如所希望的那样!

Playground link to code

【讨论】:

    猜你喜欢
    • 2021-10-04
    • 2022-10-13
    • 1970-01-01
    • 2022-11-22
    • 2019-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多