如何强制方法参数值成为接口的元素

时间:2018-06-27 04:28:45

标签: typescript

我想强制方法参数值为Interface的任何元素。

例如,

我有这样的Interface

interface User {
  userId : number;
  userName : string;
}

,并且参数应为userIduserName。所以我定义了这样的方法

setUserState = (key : User , newValue : string) => {
      // Some code here
}

显然,它不起作用。因此,我尝试了key : Partial<User>,但没有用。

我知道可以这样实现

setUserState = (key : 'userName' | 'userId' , newValue : string) => {
   // Some code here
} 

但是问题是,每当我用新的User更新element接口时,我也必须更新方法签名。少了点。

那么,强制参数值成为Interface元素的最佳方法是什么?有可能吗?

编辑1

是否有AnyOf<User>种操作符?

编辑2

我正在使用Version 2.9.2

注意:我是TypeScript的新朋友。

3 个答案:

答案 0 :(得分:2)

您可以使用keyof运算符将第一个参数限制为User属性之一。然后,您可以使用类型查询来限制第二个参数具有适当的类型:

interface User {
    userId: number;
    userName: string;
}

const user: User = { userId: 1, userName: 'userName' };

const setUserState = <TKey extends keyof User>(key: TKey, newValue: User[TKey]) => {
    user[key] = newValue;
}

setUserState('userId', 1);
setUserState('userId', '1'); //Error '"1"' is not assignable to parameter of type 'number'
setUserState('foo', 1); //Error - '"foo"' is not assignable to parameter of type '"userName" | "userId"'

泛型用于在属性值类型查询(User[TKey])中重用键类型(属性名称)。

Playground

答案 1 :(得分:1)

尝试这种方式

a
b

*

c
d

请注意:在interface User { readonly userId?: string; userName?: string; anyotherElement?: string } 之后添加?以使其可选

然后您可以将直接用户发送为参数

:

答案 2 :(得分:1)

让我们先这样尝试吧:

interface User {
    userId : number;
    userName : string;
}

const cur: User = {userId: 0, userName: 'root'}

const setUserState = (key : keyof User , newValue : string) => {
    cur[key] = newValue;
    // note: no error here, but this is erroneous,
    // as cur['userId'] is number, and newValue is string!
}

setUserState('userId', '0');
setUserState('userName', 'root');
setUserState('wrong', 'wrong');

请注意函数内部的注释:一方面,它表明keyof类型定义对于通过此键访问User对象的字段是完全正常的,但另一方面则您必须自己处理特定字段的所有类型检查。 TypeScript将无法检查newValue参数类型以匹配User的相应字段。