TypeScript keyof 和 typeof

Posted Himmelbleu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TypeScript keyof 和 typeof相关的知识,希望对你有一定的参考价值。

typeof

typeof 是 JS 本身就有的一个操作符,只不过在 TS 中多了一个功能。typeof 在 JS 中是获取变量的类型字符串:

console.log(typeof 42);
// "number"
console.log(typeof \'blubber\');
// "string"
console.log(typeof true);
// "boolean"

在 TS 中的 typeof 可以返回一个变量的 TS 类型,也可以返回一个变量的类型字符串:

let num = 42;
type A1 = typeof num;
//   ^? number

console.log(typeof 42);
// "number"

区别之处就是你要用在 interface 或者 type 关键字声明的类型变量中,而不是当做一个普通变量进行输出。

注意:TS 的类型不可以直接通过 log 打印到控制台,只有变量才可以,而非类型变量。

keyof

keyof 不是 JS 特有的,而是 TS 特有的,keyof 用于得到一个对象的属性的联合类型。

interface Person 
    name: string;
    age: number;


type A1 = keyof Person;
//   ^? "name" | "age"

keyof 操作的是一个 TS 类型;typeof 操作的是一个变量,返回变量对应的类型字符串或变量对应的 TS 类型。

keyof 和 typeof

typeof 操作一个变量,运算出 TS 类型,keyof 运算一个已知的 TS 类型。两者结合起来:keyof 通过由 typeof 运算的对象的 TS 类型,从而得到该对象的属性联合类型。

const obj = 
    name: "小明",
    age: 12


type A1 = keyof typeof obj;
//   ^? "name" | "age"

如果 obj 每一次的属性都是不一样的,两者结合起来可以实现动态得到一个对象的 TS 类型,非常的有用!

Typescript 'keyof' 关键字在使用 react setState 函数时出错

【中文标题】Typescript \'keyof\' 关键字在使用 react setState 函数时出错【英文标题】:Typescript 'keyof' keyword makes error when using with react setState functionTypescript 'keyof' 关键字在使用 react setState 函数时出错 【发布时间】:2018-11-15 20:10:16 【问题描述】:

我正在用 react 和 typescript 编写 Simple LoginForm。

interface State 
    username: string;
    password: string;


class LoginForm extends React.Component<Props, State> 
    readonly state: Readonly<State> = 
        username: '',
        password: ''
    

    onChange = (key: keyof State) => (e: React.FormEvent<HTMLInputElement>) => 
        const value = e.currentTarget.value;
        this.setState( [key]: value );  // error
    

    render() 
        return (
            ...
            <TextField
                ...
                onChange=this.onChange('username')
            />
            <TextField
                ...
                onChange=this.onChange('password')
            />
            ...
        )
    

Typescript 在 setState 行中编译失败,出现错误。

类型参数 ' [x: string]: string; ' 不可分配给“State |”类型的参数((prevState: Readonly, props: Props) => State | Pick'. 类型 ' [x: string]: string; 中缺少属性 'username' '。

this.onChange 函数中的“key”参数只允许“用户名”或“密码”,如我所料。这意味着打字稿知道 typeof 'key' 参数必须是 'username' 或 'password'。这很明显,因为我将其定义为 (key: key of State)。

但是为什么在 setState 函数中,typeof 'key' 参数变成了普通字符串呢?

谢谢。

【问题讨论】:

【参考方案1】:

添加它作为替代方案,因为这解决了我的问题。

似乎在设置状态 this.setState(prop: value) 时,React TS 有时可以期待完整的 state@jcalz 对所选答案的推测。

this.setState(
      ...this.state,
      [key]: value
);

有关此问题的最佳做法的更多信息,请点击此处: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/26635

【讨论】:

【参考方案2】:

试试这个代码:

onChange = (key: keyof IState) => (event: React.FormEvent<HTMLInputElement>) => 
    this.setState(
      [key]: event.currentTarget.value
     as Pick<IState, keyof IState>);

【讨论】:

【参考方案3】:

您遇到了known TypeScript bug,其中联合类型的计算属性被扩展为索引签名。 看起来对于 TypeScript 3.0,这将是 fixed,但这并不确定。

您现在应该使用的解决方法是 assert 该对象是预期的类型:

this.setState( [key]: value  as Record<typeof key, typeof value>);

我对 React 不够熟悉,无法知道 setState() 是否期待完整的 State,但请注意 [key]: value Partial&lt;State&gt;,因为它不会同时包含键...和 ​​TypeScript不会抓住这个,因为key 是一个联合类型。所以在运行时要小心。您可能希望将断言作为

this.setState( [key]: value  as Partial<State>);

如果这导致了错误,那么你应该修复它。

希望对您有所帮助。祝你好运!

【讨论】:

谢谢。你节省了我的时间。

以上是关于TypeScript keyof 和 typeof的主要内容,如果未能解决你的问题,请参考以下文章

[TypeScript] type、typeof、keyof

ts基本类型 typeof 和keyof

打字稿:对象和原语之间的keyof typeof联合总是永远不会

Typescript 'keyof' 关键字在使用 react setState 函数时出错

Typescript中括号和keyof的几个特殊用法

Typescript中括号和keyof的几个特殊用法