Typescript 我是否可以使用类型作为值(或从构造函数参数正确推断泛型类类型)?
我有一个泛型类,它接受另一个类型和这个类型的键名。我还想用这个密钥名初始化属性。我已经在TS中定义了它,但我必须显式地将键的名称作为泛型参数传递给构造函数,并将相同的值传递给构造函数。看起来有点不必要-这些值总是相同的类型和值 是否可以从泛型类的构造函数参数推断其类型?或者使用泛型类型作为值,可能不是-我有一个错误:“ValueKey”只引用一个类型,但在这里被用作值。ts2693 带定义的代码:Typescript 我是否可以使用类型作为值(或从构造函数参数正确推断泛型类类型)?,typescript,typescript-generics,Typescript,Typescript Generics,我有一个泛型类,它接受另一个类型和这个类型的键名。我还想用这个密钥名初始化属性。我已经在TS中定义了它,但我必须显式地将键的名称作为泛型参数传递给构造函数,并将相同的值传递给构造函数。看起来有点不必要-这些值总是相同的类型和值 是否可以从泛型类的构造函数参数推断其类型?或者使用泛型类型作为值,可能不是-我有一个错误:“ValueKey”只引用一个类型,但在这里被用作值。ts2693 带定义的代码: interface InterfaceWithProperties { stringPro
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');
或者像这样的smth:
const test2 = new GenericCLass<InterfaceWithProperties, 'stringProperty'>();
const test3 = new GenericCLass<InterfaceWithProperties>('stringProperty');
使用以下代码执行操作:问题是您希望手动指定一个类型参数,并让编译器推断另一个类型参数。这被调用,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">
这样就只剩下类定义了,但创建了一个新的helper函数,该函数返回部分指定版本的GenericClass构造函数供您使用。你可以一次完成,但很难看:
const test = new (genericClassMaker<InterfaceWithProperties>())('stringProperty');
// inferred as GenericCLass<InterfaceWithProperties, "stringProperty">
不管怎样,希望其中一个对你有用。祝你好运 问题是您想要手动指定一个类型参数,并让编译器推断另一个类型参数。这被调用,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">
这样就只剩下类定义了,但创建了一个新的helper函数,该函数返回部分指定版本的GenericClass构造函数供您使用。你可以一次完成,但很难看:
const test = new (genericClassMaker<InterfaceWithProperties>())('stringProperty');
// inferred as GenericCLass<InterfaceWithProperties, "stringProperty">
不管怎样,希望其中一个对你有用。祝你好运 坏消息是你不能轻易做到这一点。最好的方法是让编译器根据构造函数参数推断ExactKey。只有让typescript推断出所有类型参数,才能做到这一点。但是您需要指定一个类型参数并推断另一个,这是不可能的,因为至少在3.5中不支持部分推断,有计划添加它,但它被推回,然后从路线图中删除 一种选择是将函数curry与静态函数而不是构造函数一起使用:
interface InterfaceWithProperties {
stringProperty: string;
numberProperty: number;
}
class GenericCLass<TypeWithKeys, ExactKey extends keyof TypeWithKeys> {
keyNameFromAnotherType: ExactKey;
private constructor(keyNameFromAnotherType: ExactKey) {
this.keyNameFromAnotherType = keyNameFromAnotherType;
}
static new<T>(){
return function <ExactKey extends keyof T>(keyNameFromAnotherType: ExactKey) {
return new GenericCLass<T, ExactKey>(keyNameFromAnotherType);
}
}
}
const test1 = GenericCLass.new<InterfaceWithProperties>()('stringProperty')
或者,如果您害怕使用null作为InterfaceWithProperties,则可以使用类型类:
这两种解决方案都不是很好,也不是特别直观,都不是最好的解决方案。最糟糕的新情况是,你不能轻易做到这一点。最好的方法是让编译器根据构造函数参数推断ExactKey。只有让typescript推断出所有类型参数,才能做到这一点。但是您需要指定一个类型参数并推断另一个,这是不可能的,因为至少在3.5中不支持部分推断,有计划添加它,但它被推回,然后从路线图中删除 一种选择是将函数curry与静态函数而不是构造函数一起使用:
interface InterfaceWithProperties {
stringProperty: string;
numberProperty: number;
}
class GenericCLass<TypeWithKeys, ExactKey extends keyof TypeWithKeys> {
keyNameFromAnotherType: ExactKey;
private constructor(keyNameFromAnotherType: ExactKey) {
this.keyNameFromAnotherType = keyNameFromAnotherType;
}
static new<T>(){
return function <ExactKey extends keyof T>(keyNameFromAnotherType: ExactKey) {
return new GenericCLass<T, ExactKey>(keyNameFromAnotherType);
}
}
}
const test1 = GenericCLass.new<InterfaceWithProperties>()('stringProperty')
或者,如果您害怕使用null作为InterfaceWithProperties,则可以使用类型类:
这两种解决方案都不是好的,也不是特别直观的,都是最好的解决方案。伟人的想法是一样的:我留下我的答案,因为我认为类型版本可能有一些用途,您的函数返回构造函数方法也很好,这两个答案都很好,并且建议使用类型来删除null强制转换!我使用@jcalz中的curry helper函数,因为我需要的是构造函数本身,而不是实例。非常感谢-每件事都很有魅力:伟大的思想都是一样的:我将留下我的答案,因为我认为类型版本可能有一些用途,而你的有函数返回构造函数的方法,这也很好。两个答案都很好,并且建议使用类型来删除null强制转换!我使用@jcalz中的curry helper函数,因为我需要的是构造函数本身,而不是实例。非常感谢-一切都很有魅力: