博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
TypeScript 2.9
阅读量:7051 次
发布时间:2019-06-28

本文共 6107 字,大约阅读时间需要 20 分钟。

keyof 功能增强

keyof 和映射类型支持 numbersymbol 类型的属性名称

在索引类型和映射类型中,TypeScript 2.9 新增了对 numbersymbol 类型属性名称的支持。在之前的版本,keyof 和映射类型支持 string 类型的属性名称。

新功能带来的变化包括:

  • 对于类型 Tkeyof T 的索引类型是 string | number | symbol 的子类型
  • 映射类型 { [P in K]: XXX } 会映射所有兼容 string | number | symbolK
  • 对于 for...in 语句中泛型为 T 的对象,迭代变量的类型在之前推断为 keyof T,但是现在推断为 Extract<keyof T, string>(即,只包含 keyof T 中的类字符串值)

给定一个对象类型 Xkeyof X 的类型求值过程如下:

  1. 如果 X 包含字符串索引签名,那么 keyof X 的值为 stringnumber 和类符号属性名的字面量类型组成的联合类型,否则下一步
  2. 如果 X 包含数值索引签名,那么 keyof X 的值为 number 和类字符串与类符号属性名的字面量类型组成的联合类型,否则下一步
  3. keyof X 的值为类字符串、类数值和类符号属性名的字面量类型组成的联合类型

其中,

  • 对象的类字符串(string-like)属性名包括标识符、字符串字面量和字符串字面量类型的计算属性名
  • 对象的类数值(number-like)属性名包括数值字面量和数值字面量类型的计算属性名
  • 对象的类符号(symbol-like)属性名包括符号类型的计算属性名

在映射类型 { [P in K]: XXX } 中,K 中的每一个字符串字面量类型都会引入一个字符串名称的类型,每一个数值类型字面量类型都会引入一个数值名称的类型,每一个符号类型都会引入一个符号名称的类型。此外,如果 K 包含 string 类型,那么会引入一个字符串索引签名,如果包含 number 类型,也会引入一个数值索引签名。

上面的文字可能不太好理解,来看看下面的例子:

const c = "c";const d = 10;const e = Symbol();const enum E1 { A, B, C }const enum E2 { A = "A", B = "B", C = "C" }type Foo = {    a: string;      // string-like,标识符    5: string;      // number-like, 数值字面量    [c]: string;    // string-like, 字符串字面量类型的计算属性    [d]: string;    // number-like, 数值字面量类型的计算属性    [e]: string;    // symbol-like, 符号类型的计算属性    [E1.A]: string; // number-like, 数值枚举类型的计算属性    [E2.A]: string; // string-like, 字符串枚举类型的计算属性}type K1 = keyof Foo; // "a" | 5 | "c" | 10 | typeof e | E1.A | E2.A;type K2 = Extract
; // "a" | "c" | E2.Atype K3 = Extract
; // 5 | 10 | E1.Atype K4 = Extract
; // typeof e

现在,由于 keyof 可以通过在键名类型中使用 number 来映射到数值索引签名,所以诸如 Partial<T>Readonly<T> 的映射类型能够正确地处理对象类型中的数值索引签名了。

type Arrayish
= { length: number; [x: number]: T;}type ReadonlyArrayish
= Readonly
>;declare const map: ReadonlyArrayish
;let n = map.length;let x = map[123]; // x 推断为 string,之前版的版本会推断为 any

此外,得益于 keyof 操作支持使用 numbersymbol 命名的键值,当一个对象使用数值字面量(如数值枚举类型)和唯一符号作为属性索引时,现在我们可以把访问对象属性的过程独立地抽象出来了。

const enum Enum { A, B, C }const enumToStringMap = {    [Enum.A]: "Name A",    [Enum.B]: "Name B",    [Enum.C]: "Name C"}const sym1 = Symbol();const sym2 = Symbol();const sym3 = Symbol();const symbolToNumberMap = {    [sym1]: 1,    [sym2]: 2,    [sym3]: 3};type KE = keyof typeof enumToStringMap;     // Enum (i.e. Enum.A | Enum.B | Enum.C)type KS = keyof typeof symbolToNumberMap;   // typeof sym1 | typeof sym2 | typeof sym3function getValue
(obj: T, key: K): T[K] { return obj[key];}let x1 = getValue(enumToStringMap, Enum.C); // x1 类型为 string ,返回 "Name C"let x2 = getValue(symbolToNumberMap, sym3); // x1 类型为 number ,返回 3

这是一项重大功能变更。在之前的版本中,keyof 和映射类型只支持 string 类型命名的属性。现在,如果还认为 keyof T 的类型值总是 string 的话,那么将会抛出错误,因为此时 keyof T 的类型值为 string | number | symbol。举例如下:

function useKey
(o: T, k: K) { var name: string = k; // Error: keyof T is not assignable to string}

针对该重大功能变更,有以下建议:

  • 如果函数只允许处理 string 类属性名,那么可以使用 Extract<keyof T, string>:
function useKey
>(o: T, k: K) { var name: string = k; // OK}
  • 如果函可以处理其他类型的属性键名,那么可以使用如下的做法:
function useKey
(o: T, k: K) { var name: string | number | symbol = k;}
  • 否则,使用 --keyofStringsOnly 编译选项来禁用新功能

JSX 泛型参数

现在,JSX 支持传递泛型参数给泛型组件了。

class GenericComponent

extends React.Component

{ internalProp: P;}type Props = { a: number; b: string; };const x =

a={10} b="hi"/>; // OKconst y =
a={10} b={20} />; // Error

标签模板泛型参数

标签模板是 ES2015 引入的一种新调用方式。跟调用表达式一样,泛型函数也可用在标签模板中,TypeScript 会根据类型参数进行类型推断。

TypeScript 2.9 支持向标签模板字符串传递泛型类型参数。

declare function styledComponent
(strs: TemplateStringsArray): Component
;interface MyProps { name: string; age: number;}styledComponent
` font-size: 1.5em; text-align: center; color: palevioletred;`;declare function tag
(strs: TemplateStringsArray, ...args: T[]): T;// a 的类型为 string | numberlet a = tag
`${100} ${"hello"}`;

import 类型

模块可以导入其他模块的类型声明。但是,非模块化的全局脚本无法访问模块的类型声明。import 为此打开了新世界的大门。

通过在类型注释中使用 import("mod"),我们可以访问到该模块导出的类型声明,同时模块代码也并不会因此而引入。

来看一个简单的例子。

假如模块中有以下声明:

// module.d.tsexport declare class Pet {    name: string;}

那么就可以在非模块化的全局脚本中按以下方式使用它:

// global-script.tsfunction adopt(p: import("./module").Pet) {    console.log(`Adopting ${p.name}...`);}

也可以在 JSDoc 注释中使用它:

// a.js/** * @param p { import("./module").Pet } */function walk(p) {    console.log(`Walking ${p.name}...`);}

消除声明错误

支持 import 类型后,声明文件生成过程中抛出的许多错误可以由编译器直接处理,而不需要改变原输入文件。

例如:

import { createHash } from "crypto";export const hash = createHash("sha256");//           ^^^^// 导出变量 'hash' 已经或正在使用外部模块 "crypto" 中的名称 'Hash',但无法对其命名

在 TypeScript 2.9 中,这样的错误就不会抛出来了,并且生成的声明文件如下:

export declare const hash: import("crypto").Hash;

支持 import.meta

TypeScript 2.9 引入了对 import.meta 的支持,它是 中的一种新的元属性(meta-property)。

import.meta 的类型由全局类型 ImportMeta 所定义,位于 lib.es5.d.ts 。该接口的使用范围是很受限的,主要用来为 Node 或者浏览器添加众所周知的属性,以及可能根据上下文进行的全局增强。

例如,假设 __dirnameimport.meta 中总是可用的,那么就可以通过 ImportMeta 接口来新增该属性:

// node.d.tsinterface ImportMeta {    __dirname: string;}

使用方法如下:

import.meta.__dirname // 类型为 'string'

import.meta 只能在编译输出为 ESNext 模块和 ECMAScript 时使用。

编译选项

--resolveJsonModule

在 Node.js 应用中,通常都会使用 .json 文件。在 TypeScript 2.9 中,--resolveJsonModule 编译选项可允许从 .json 中导入、导出其类型。

// settings.json{    "repo": "TypeScript",    "dry": false,    "debug": false}
import settings from "./settings.json";settings.debug === true;  // OKsettings.dry === 2;  // Error: '===' 不能用于比较 boolean 和 number 类型
// tsconfig.json{    "compilerOptions": {        "module": "commonjs",        "resolveJsonModule": true,        "esModuleInterop": true    }}

--pretty

自 TypeScript 2.9 开始,如果输出设备支持多颜色文本,错误信息将默认开启 --pretty 选项。TypeScript 会自动检查输出流是否设置 isTty 属性。

可以在命令行使用 --pretty false 或者 tsconfig.json 中设置 "pretty": false 来禁用 --pretty 输出。

--declarationMap

如果在开启 --declaration 的情况下,同时开启 --declarationMap ,那么编译器会同时生成 .d.ts.d.ts.map 文件。语言服务现在能够正确识别这些映射文件,并且使用它们来映射到源码。

也就是说,在使用“跳到定义之处”功能时,会直接跳转到源码文件,而不是 .d.ts 文件。

转载地址:http://lwvol.baihongyu.com/

你可能感兴趣的文章
css3过度属性,2D3D转换,动画
查看>>
excel单元格内容换行
查看>>
[转载]基于TFS实践敏捷-工作项跟踪
查看>>
第5章 发布循环
查看>>
查询某软件所连接的外网IP地址
查看>>
Makefile编写示例:构建一个库
查看>>
[Machine Learning]Markov chain and Hidden Markov Models(HMMs)
查看>>
C# 修饰符的总结 default public private protected internal protectedinternal
查看>>
对于软件,我是认真的
查看>>
"https://open.gl/"教程之Transforms源码(freeglut版)
查看>>
接口自动化:pytest----环境搭建
查看>>
团队编程项目开发环境搭建过程
查看>>
[LeetCode]Integer to English Words
查看>>
springboot之模板
查看>>
Javascript 中 检查一个数组是否包含某对象
查看>>
5月20日工作日志(奇异森林完工部分截图)
查看>>
navicat for mysql 安装教程
查看>>
八,裁剪linux3.19.9内核,制作jffs2和yaffs2根文件系统
查看>>
java面试每日一题11
查看>>
CentOs 6.5设置使用私钥登录关闭ssh的密码登录修改ssh默认端口
查看>>