基于第一个参数类型的 TypeScript 第二个参数类型

Cri*_*sty 7 javascript enums types overloading typescript

我有第一个参数的可能值枚举,我希望第二个参数基于第一个参数。因此,如果给出 NAME,我希望第二个参数为字符串。如果给出 AGE,我希望第二个参数是一个数字。

我怎么能做这样的事情?

enum KeyType {
   NAME,
   AGE
}

class MyClass {
   public static setProperty(key: KeyType.NAME, value: string): void { }
   public static setProperty(key: KeyType.AGE, value: number): void { } 
}
Run Code Online (Sandbox Code Playgroud)

我想像这样调用方法:
MyClass.setProperty(KeyType.NAME, 'John');

此外,这应该显示一个错误:
MyClass.setProperty(KeyType.NAME, 5);// 5 is not a string

在这个例子中它不起作用,因为key类型定义错误(键类型实际上是枚举的值,所以键类型是0)。

我也愿意接受有关使用此功能的不同方法的建议,即仅允许特定参数键的特定类型。

Dun*_*can 6

您想使用函数重载来使类型检查正常工作:

enum KeyType {
   NAME,
   AGE
}

class MyClass {
   public static setProperty(key: KeyType.NAME, value: string): void;
   public static setProperty(key: KeyType.AGE, value: number): void;
   public static setProperty(key: KeyType, value: (string | number)): void {}
}
Run Code Online (Sandbox Code Playgroud)

或者更简单,只需使用字符串:

class MyClass {
   public static setProperty(key: 'name', value: string): void;
   public static setProperty(key: 'age', value: number): void;
   public static setProperty(key: string, value: (string | number)): void {}
}

MyClass.setProperty('name', 42); // Argument of type '"name"' is not assignable to parameter of type '"age"'.
MyClass.setProperty('age', 42); // Ok
MyClass.setProperty('name', 'foo'); // Ok
MyClass.setProperty('age', 'foo'); // Argument of type '"foo"' is not assignable to parameter of type 'number'.
Run Code Online (Sandbox Code Playgroud)

当然,您不必在重载中列出文字字符串,您可以将类似的字符串分组到一个类型定义中:

type StringProperty = 'name' | 'address';
type NumberProperty = 'age' | 'salary';
class MyClass {
   public static setProperty(key: StringProperty, value: string): void;
   public static setProperty(key: NumberProperty, value: number): void;
   public static setProperty(key: string, value: (string | number)): void {}
}
Run Code Online (Sandbox Code Playgroud)