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

理解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源代码的时候需要额外地注意这样一些灵活之处。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 34,561评论 18 399
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 136,465评论 19 139
  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young阅读 4,169评论 1 10
  • 从腊月底到正月初,我有两位同学结婚。大喜的日子正好赶在假期,难得,聚少离多的同学们从祖国各地前来道喜,可喜可贺,我...
    小马哥的写生簿阅读 409评论 0 0
  • 儿子这个月刚满两岁,最近两天发现他的自尊心变得好大!不能受气!不能说!甚至大声一点点的斥责,他立刻委屈给你看…… ...
    昨天之前明天以后阅读 231评论 0 0

友情链接更多精彩内容