美文网首页Web前端之路Web 前端开发 我爱编程
理解TypeScript中的一个(伪)黑魔法

理解TypeScript中的一个(伪)黑魔法

作者: Huisama | 来源:发表于2017-02-23 20:13 被阅读1482次

理解TypeScript中的一个(伪)黑魔法

最近在学习TypeScript的时候,看到高级类型这里,对

function pluck<T, K extends keyof T>(o: T, names: K[]): T[K][] {
    return names.map(n => o[n]);
}

interface Person {
    name: string;
    age: number;
}

let person: Person = {
    name: 'Jarid',
    age: 35
};

let strings: string[] = pluck(person, ['name']); 

这段代码有点不太理解,感觉像是黑魔法一般,主要的疑惑点在于:

let strings: string[] = pluck(person, ['name']);

这段代码,传入给pluck的应该是一个string[],那么泛型函数

function pluck<T, K extends keyof T>(o: T, names: K[]): TK;

这个签名应该被替换为,

function pluck<Person, string extends keyof Person>(o: Person, names: string[]): Person[string][];

其中

keyof Person

等价于

'name' | 'age'

于是对于约束:

string extends 'name' | 'age'

而言,就是绝对通不过静态类型检查的,但是在这里却是能够通过的,这让我百思不得其解。

后来我怀疑自己看漏了什么重要的东西,于是把文档往上翻,在字符串字面量类型这里,看到了一点端倪,于是我在TypeScript中做了这样子的尝试:

type MyType = 'myType';
function bar(param : MyType[]) : void {
    console.log(param);
}
bar(['myType']);

结果是输出了:

["myType"]

于是我恍然大悟,在前面的代码中TypeScript的类型约束事实上是做了这样子的工作:

  1. 通过

    keyof Person
    

    获得了

    "name" | "age"
    
  2. 根据

    K extends keyof Person
    

    约束了K要么是“name”要么是“age”**

    假设如果两者都不是,那么静态检查将会直接报错;

  3. 现在静态检查器来检查

    names : K[]
    

    由于传入的是['name'],那么首先如果将其解释为string[]的话显然是不对的,那么进一步地,TypeScript静态检查器尝试将['name']中的'name'看成是一个字符字面量类型,然后将其解释为'name'[],即字符字面量类型数组,这样一来,泛型变量K就是'name',约束'name' extends 'name' | 'age'就顺利通过了。**

  4. 进一步的,T[K]事实上就是Person['name'],而Person['name']就是string所以这个函数的返回值就是string[]

为了验证我的猜想,我把最后那行调用改成了

let strings: string[] = pluck(person, ['name', 'name', 'name']); 

然后测试的时候输出:

["Jarid", "Jarid", "Jarid"]

这符合我的理解。

总结一下,其实理解这个问题最大的关键就是理解TypeScript字符串字面量类型这个概念,这个概念使得TypeScript的静态检查变得相当灵活,从上面的描述我们可以看出'name'这个字符串使得TypeScript静态分析的时候做了一定的推断(可能推断过程和我的描述并非一致,因为我还没有仔细研读过TypeScript的源代码),这使得我们在阅读TypeScript源代码的时候需要额外地注意这样一些灵活之处。

相关文章

  • 理解TypeScript中的一个(伪)黑魔法

    理解TypeScript中的一个(伪)黑魔法 最近在学习TypeScript的时候,看到高级类型这里,对 这段代码...

  • TypeScript Fit in React 小教程

    TypeScript TypeScript TypeScript可以理解为是JavaScript的一个超集,也就是...

  • js和ts

    TypeScript是 JavaScript 的一个超集,typeScript代码更简洁,更好理解,更易于维护。一...

  • CSS - 伪元素

    CSS伪元素 Pseudo-elements 理解:可以理解伪元素是元素中的一部分,不是一个真实的元素,与元素有相...

  • React开发问题总结(持续更新...)

    1.Typescript中的&理解 参数中的 & 表示props对象同时拥有了TagManagementState...

  • 协变与逆变

    必看 协变与逆变 | 深入理解 TypeScript TypeScript: Playground

  • TypeScript中理解工厂模式

    工厂模式相当于有一个工厂类,专门生产对象的,你告诉工厂需要生产什么样的对象,它就按照你的需求生产出什么样的对象,而...

  • TypeScript中理解代理模式

    代理模式主要的思想是假如某个人要去做一件事,TA这个人不是自己亲自去做,而是让一个“代理人”去做这件事。好比你租房...

  • TS 笔记五 索引签名

    参考深入理解Typescript 索引签名[https://jkchao.github.io/typescript...

  • typescript基本特性了解

    本文主要给大家介绍typescript的基本特性。 1、typeScript中的数据类型 typescript中为...

网友评论

    本文标题:理解TypeScript中的一个(伪)黑魔法

    本文链接:https://www.haomeiwen.com/subject/gfabwttx.html