我可以使用类型作为值(或从构造函数参数正确推断通用类类型)吗?

交叉

我有一个通用的类,它接受其他类型和该类型的键名。我还想用此键名初始化属性。我已经在TS中定义了它,但是我必须将键的名称显式传递为泛型参数,并将相同的值传递给构造函数。看起来有点不必要-这些值始终相同(类型和值)。

是否可以从其构造函数参数推断通用类的类型?或者使用通用的“类型”作为“值”(可能不是-我遇到了错误:)'ValueKey' only refers to a type, but is being used as a value here.ts(2693)

定义代码:

interface InterfaceWithProperties {
    stringProperty: string;
    numberProperty: number;
}

class GenericCLass<TypeWithKeys, ExactKey extends keyof TypeWithKeys> {
    keyNameFromAnotherType: ExactKey; // this property should have value equal to key from another type;

    // is it a way to remove this parameter? it's exactly duplicated with ExactKey
    // or to detect correctly ExactKey type based on `property` value
    constructor(keyNameFromAnotherType: ExactKey) {
        // this.property = ExactKey; // ofc: not working code
        this.keyNameFromAnotherType = keyNameFromAnotherType;
    }
}

当前用法:

const test1 = new GenericCLass<InterfaceWithProperties, 'stringProperty'>('stringProperty');

我想要相同的结果,但没有这个额外的参数。像这样:

const test2 = new GenericCLass<InterfaceWithProperties, 'stringProperty'>();

或像这样:

const test3 = new GenericCLass<InterfaceWithProperties>('stringProperty');

带有以下代码的TS游乐场:链接

贾卡尔兹

问题是您要手动指定一个类型参数,并让编译器推断另一个参数。这就是所谓的部分类型参数推论,而TypeScript则没有(从TS3.4开始)。您既可以手动指定所有类型参数(不想执行),也可以让所有类型参数由编译器推断(您不能这样做,因为您无法从中推断出指定的类型)。

对于这种情况,有两种主要的解决方法:

第一种是完全依靠类型推断,并使用虚拟参数来推断您通常指定的类型。例如:

class GenericCLass<T, K extends keyof T> {
    keyNameFromAnotherType: K; 

    // add dummy parameter
    constructor(dummy: T, keyNameFromAnotherType: K) {
        this.keyNameFromAnotherType = keyNameFromAnotherType;
    }
}

const test = new GenericCLass(null! as InterfaceWithProperties, 'stringProperty');
// inferred as GenericCLass<InterfaceWithProperties, "stringProperty">

您可以看到作为第一个参数传入的值只是null在运行时,而构造函数无论如何都不会在运行时查看它。但是类型系统已经被告知是type InterfaceWithProperties,这足以以您想要的方式推断类型。

另一个解决方法是通过currying将通常使用部分推断的任何东西分解为两部分第一个泛型函数将允许您指定一个参数,并返回一个推断另一个参数的泛型函数(在本例中为泛型构造函数)。例如

// unchanged
class GenericCLass<T, K extends keyof T> {
    keyNameFromAnotherType: K;

    constructor(keyNameFromAnotherType: K) {
        this.keyNameFromAnotherType = keyNameFromAnotherType;
    }
}

// curried helper function
const genericClassMaker =
    <T>(): (new <K extends keyof T>(
        keyNameFromAnotherType: K
    ) => GenericCLass<T, K>) =>
        GenericCLass;

// specify the one param
const InterfaceWithPropertiesGenericClass =
    genericClassMaker<InterfaceWithProperties>();

// infer the other param
const test = new InterfaceWithPropertiesGenericClass('stringProperty');
// inferred as GenericCLass<InterfaceWithProperties, "stringProperty">

这样GenericClass就不用再定义类了,而是创建一个新的帮助器函数,该函数返回部分指定版本的构造函数供您使用。您可以一次完成,但是很丑陋:

const test = new (genericClassMaker<InterfaceWithProperties>())('stringProperty');
// inferred as GenericCLass<InterfaceWithProperties, "stringProperty">

无论如何,希望其中一项对您有用。祝好运!

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

我可以使用输入模块为python中的类型构造函数创建类型别名吗?

编写可能最终传递任何类型的结构的函数时,可以使用接口作为参数吗?

您可以使用无类型对象实例化Java类构造函数吗?

我可以传递“类型”作为函数参数吗?

从单个构造函数参数推断通用类类型参数

我可以使用DataKinds编写一个返回参数编码类型的值的函数吗?

函数的类型推断作为参数

我可以在外部构造函数中为参数类型构建无参数构造函数吗?

我可以使用本地声明的枚举类作为模板非类型参数吗?(gcc给出了模糊的错误)

我可以使用集合类型作为数组索引吗?

可以使用自动占位符来推断非类型模板参数的函数结果吗?

Typescript:可以使用enum作为函数参数类型吗?

OBJ-C,我可以使用协议作为函数参数的参数类型吗?

类型构造函数可以使用与类型相同的别名吗?

我可以在通用类中使用类型缩写作为别名吗?

可以推断参数的通用接口中使用的类型吗?

我可以使用lambda指针数组来保存具有不同类型的参数/返回值的函数吗?

使用通用类的参数作为事件类型

我可以使用其他函数的类型信息作为Python中的返回类型吗?

Coq:我可以使用类型参数作为连续参数的类型吗?

我可以使用在类构造函数中初始化的ofstream类型的成员变量吗?

类型构造函数参数推断

我可以将基类类型作为通用参数传递给接口吗

我可以使用void *作为函数的参数吗?

我可以使用强类型反射找到具有通用参数的方法吗?

我可以使用 extends keyof Type 推断值的类型吗

是否可以从 Typescript 中的非构造函数方法参数推断泛型类类型?

如果基类作为参数调用,我可以使用派生类函数吗?

我可以从输入参数推断类型吗?