【问题标题】:Is there a way to have typescript infer the type for each individual index of an array without having the type parameter in the function?有没有办法让打字稿推断数组的每个单独索引的类型,而函数中没有类型参数?
【发布时间】:2021-04-13 23:42:00
【问题描述】:

标题可能令人困惑,我不知道如何正确表达它,但总之我想完成以下工作:

type A<T extends new (...args: any) => any = any> = [T, Required<InstanceType<T>>];

function b<T extends new (...args: any) => any, T2 extends new (...args: any) => any>(...args: [A<T>, A<T2>?]) { };

class C { d?: string; e?: number };

class F { g?: string; h?: number };

b([C, { d: '', e: 2 }], [F, { g: '', h: 3 }]);

但不必在b 函数中具有T, T2 类型参数,因为在我的用例中,该函数没有定义的参数长度。这可能吗?如果没有,有更好的解决方案吗?

【问题讨论】:

标签: typescript


【解决方案1】:

假设您想让b 采用任意数量的A 类型的参数,这本身就是参数,那么不幸的是没有。 可能这样做是一种 hacky 方式,但它肯定不干净,并且可能依赖递归类型来处理强制数组的第二个成员基于第一个成员进行类型检查。

核心问题是 Typescript 不支持更高种类的类型。所以你需要的是可以通过Array&lt;T&gt; 参数化的东西,其中T 通过A&lt;K&gt; 参数化。这意味着需要一个函数,b,看起来像这样

export declare function b<T extends A<K>[]>(...args: T);

其中bT 上参数化,K 上参数化。这是目前在 TypeScript 中无法实现的。

您可以省略K 上的参数化并拥有

export declare function b<T extends A[]>(...args: T);

但是,使用上面的 TypeScript 将无法强制执行数组的类型。例如,它会允许 b([C, { doesnt_exist: '', e: true }]); 缺少 C 类中所需的 d 属性,而 e 的类型错误。

为了在 TypeScript 中正确执行此操作,您需要将此函数的实现拆分为两个不同的函数,每个函数只能对一个类型参数进行参数化。

type A<T extends new (...args: any) => any = any> = [T, Required<InstanceType<T>>];

function makeA<T extends new (...args: any) => any>(a: A<T>) {return a;}

function b<T extends A[]>(...args: T) { };

class C { d?: string; e?: number };

class F { g?: string; h?: number };

class I { j?: string; k?: number };

b(makeA([C, { d: 'hello', e: 4 }]), makeA([F, { g: 'string', h: 5 }]), makeA([I, { j: 'test', k: 6 }]));

所以现在bArray&lt;T&gt; 的参数,makeAA&lt;K&gt; 的参数。因此,将两者结合起来,您基本上可以得到您正在寻找的更高种类的类型,尽管它不像在 Haskell 中那样实用。

以这种方式使用b 函数更难,但您将获得b 的每个参数的类型安全性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-23
    • 2020-03-22
    • 2016-09-21
    • 1970-01-01
    • 2020-09-21
    • 2021-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多