资讯专栏INFORMATION COLUMN

TypeScript 2.7 记录

2bdenny / 2298人阅读

摘要:版本记录针对版本的特性作专门的实例,希望能加深理解。这种情况下添加类型属性被间接初始化了例如构造函数中调用一个方法,更改了属性的值。这种情况下我们可以使用显式赋值断言修饰符号来帮助类型系统识别类型。

TypeScript 2.7版本记录
针对ts 2.7版本的特性作专门的实例,希望能加深理解。实例github地址 官方日志文档
增加常量声明的属性的支持(Constant-named properties) 对于常量,有更加智能的提示
const Foo = "Foo";
const Bar = "Bar";

let x = { // 2.7版本之前,x的类型为{[x:string]:string|number},现在为 {[Foo]: number;[Bar]: string;}}
    [Foo]: 100,
    [Bar]: "hello",
};

let a = x[Foo]; // has type "number"
let b = x[Bar]; // has type "string"
typescript 增加一种新的类型声明:unique symbols,是 symbols的子类型,仅可通过调用 Symbol()或 Symbol.for()或由明确的类型注释生成

ES6 引入的 Symbol 机制,Symbol是js的第七种数据类型,可以产生独一无二的值,可以用来保证每个属性的名字都是独一无二,从根本上防止属性名的冲突。结合ts,我们可以这样声明一个symbol,const Foo: unique symbol = Symbol()

unique symbol 类型必须由 const 关键字声明

// Error! "Bar" isn"t a constant.
let Bar: unique symbol = Symbol();

引用赋值一个 unique symbol 类型的值时候使用 typeof 操作符

// let Baz = Foo // 这样的话 Baz 的类型为symbol
let Baz: typeof Foo = Foo // 类型为unique symbol
// 在class里面使用 `unique symbol` 定义类的静态属性(不能用在类属性) 时,
// 需要使用 `readonly static` 关键字来声明
class C {
    static readonly StaticSymbol: unique symbol = Symbol();
}

当Symbol + const时,值的类型自动判断为unique symbol

// let SERIALIZE = Symbol("serialize-method-key"); SERIALIZE 类型为symbol
const SERIALIZE = Symbol("serialize-method-key");  // SERIALIZE 类型为unique symbol

接口中的计算属性名称引用必须引用类型为文本类型或 "unique symbol"

interface Serializable {
   // [("serialize-method-key")](obj: {}): string; //error
   [SERIALIZE](obj: {}): string;
}

class JSONSerializableItem implements Serializable {
   //  error 只能用引入的SERIALIZE来作属性的名称
   // ["serialize-method-key"](obj: {}) {
   //     return JSON.stringify(obj);
   // }
   [SERIALIZE](obj: {}) {
       return JSON.stringify(obj);
   }
}

另外,两个unique symbol类型的值不能互相比较(当然除非其中一个值的类型为用 typeof 另外一个值)

新编译选项,更严格的类属性检查( --strictPropertyInitialization)

TypeScript 2.7引入了一个新的控制严格性的标记 --strictPropertyInitialization

现在,如果开启 strictPropertyInitialization,我们必须要确保每个实例的属性都会初始值,可以在构造函数里或者属性定义时赋值。

class StrictClass {
    foo: number;
    bar = "hello";
    baz: boolean; 
    // error,Property "baz" has no initializer and is not definitely assigned in the constructor
    constructor() {
        this.foo = 42;
    }
}

有两种情况下我们不可避免该error的产生:

该属性本来就可以是 undefined 。这种情况下添加类型undefined

属性被间接初始化了(例如构造函数中调用一个方法,更改了属性的值)。这种情况下我们可以使用 显式赋值断言 (修饰符号 !) 来帮助类型系统识别类型。后面具体介绍它,先看下代码中怎么使用:

class StrictClass {
    // ...
    baz!: boolean;
    // ^
    // 注意到这个!标志
    // 代表着显式赋值断言修饰符
}
显式赋值断言(Definite Assignment Assertions)
尽管我们尝试将类型系统做的更富表现力,但我们知道有时用户比TypeScript更加了解类型

跟上面提到的类属性例子差不多,我们无法在给一个值赋值前使用它,但如果我们已经确定它已经被赋值了,这个时候类型系统就需要我们人的介入

let x: number;
initialize();
console.log(x + x);
//          ~   ~
// Error! Variable "x" is used before being assigned.

function initialize() {
    x = 10;
}

添加 ! 修饰:let x!: number,则可以修复这个问题

我们也可以在表达式中使用!,类似 variable as stringvariable :

let x: number;
initialize();
console.log(x! + x!); //ok

function initialize() {
    x = 10;
}
添加 --esModuleInterop 对ES模块和老式代码更好的互通

这一块中文官网花了挺长篇幅来讲这个内容,我也是实践过才明白讲的是什么,需要理解 __esModule 标记是做什么的、es6模块经过ts转换成commonjs是怎么的、 如何保持与老式代码( CommonJS/AMD/UMD)的互通性

先说一下 --esModuleInterop 的作用:

默认开启allowSyntheticDefaultImports(那是肯定的,我们需要它来实现默认导入的功能)

命名空间导入不允许被调用或者构造,需要改成默认导入

import * as express from "express";
// error 正确的实现导入方式应该是下面这种

import express from "express";
express();
注意: 我们强烈建议开启esModuleInterop,不管在新代码或者是老代码上。但该模式下会可能对已有的代码产生破环,对已有的命名空间导入(import * as express from "express"; express();)改成默认导入(import express from "express"; express(); )

让我们更深入理解,在 --esModuleInterop 下,ts对 import * 和 import default两种导入方式用两个helpers __importStar and __importDefault做分别处理。

构建前的代码:

import * as foo from "foo";
import b from "bar";
const a = "newM"
export default a

构建后的代码:

"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
    result["default"] = mod;
    return result;
}
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
}
exports.__esModule = true;
var foo = __importStar(require("foo"));
var bar_1 = __importDefault(require("bar"));
const a = "newM";
exports.default = a;

这样做的结果是,我们新的代码不管是通过ts,Babel或Webpack来构建,都能通过 __esModule 来判断是否为es模块,如果无__esModule,则创建含default的对象保存模块,这样就完成我们要的默认导入功能,同时保持对老的库的支持

固定长度元祖

[number, string, string]类型的值 不可赋值 [number, string] 类型的值了。

[number, string]类型等同于下面的 NumStrTuple声明:

interface NumStrTuple extends Array {
    0: number;
    1: string;
    length: 2; // using the numeric literal type "2"
}

NumStrTuple 代表类型为固定长度为2,[0]为number类型,[1]为string 类型的数组

如果不希望固定宽度,只需要最小长度,可以这样:

interface MinimumNumStrTuple extends Array {
    0: number;
    1: string;
}
更智能的对象字面量推断
// 现在能正常判断obj的类型了,而不是之前的 {}
const obj = test ? { text: "hello" } : {};  // { text: string } | { text?: undefined }
const s = obj.text;  // string | undefined

// { a: number, b: number } |
// { a: string, b?: undefined } |
// { a?: undefined, b?: undefined }
let obj2 = [{ a: 1, b: 2 }, { a: "abc" }, {}][0];

declare function f(...items: T[]): T; 

// { a: number, b: number } |
// { a: string, b?: undefined } |
// { a?: undefined, b?: undefined }
let obj3 = f({ a: 1, b: 2 }, { a: "abc" }, {});
其它 in操作符细化和精确的 instanceof

in 操作符 和 instanceof 运算符 更好用了(就是那么简单)

--watch,--pretty 编译

--watch 会在重新编译后清空控制台
--pretty 更好地展示错误信息

看图:

完。参考:ts官方

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95072.html

相关文章

  • TypeScript - 一种思维方式

    摘要:怎么影响了我的思考方式对前端开发者来说,能强化了面向接口编程这一理念。使用的过程就是在加深理解的过程,确实面向接口编程天然和静态类型更为亲密。摘要: 学会TS思考方式。 原文:TypeScript - 一种思维方式 作者:zhangwang Fundebug经授权转载,版权归原作者所有。 电影《降临》中有一个观点,语言会影响人的思维方式,对于前端工程师来说,使用 typescript 开...

    noONE 评论0 收藏0
  • 精读《Typescript2.0 - 2.9》

    摘要:比如或者都会导致函数返回值类型时。和特性一样,等于是函数返回值中的或。注意对比下面的写法对于,它的返回值是可迭代的对象,并且每个类型都是或者。首先是不支持方法重载的,是支持的,而类型系统一定程度在对标,当然要支持这个功能。 1 引言 精读原文是 typescript 2.0-2.9 的文档: 2.0-2.8,2.9 草案. 我发现,许多写了一年以上 Typescript 开发者,对 T...

    william 评论0 收藏0
  • 前端每周清单第 50 期: AngularJS and Long Term Support, Web

    摘要:在该版本发布之后,开发团队并不会继续发布新的特性,而会着眼于进行重大的错误修复。发布每六个星期,团队就会创建新的分支作为发布通道,本文即是对新近发布的版本进行简要介绍。 showImg(https://segmentfault.com/img/remote/1460000013229009); 前端每周清单专注前端领域内容,以对外文资料的搜集为主,帮助开发者了解一周前端热点;分为新闻热...

    DobbyKim 评论0 收藏0
  • [在线+源码]vue全家桶+Typescript开发一款习惯养成APP

    摘要:基于的版本和编写的模仿原生应用的源码地址欢迎项目演示地址建议直接添加到主屏幕端体验差一些前言为什么做这个项目学习全家桶,很长一段时间在用。作者声称之后增强了对的支持,探究在中的支持情况。 vue-ts-daily 基于Vue.js的2.5.13版本和TypeScript编写的模仿原生应用的WebApp.源码地址 欢迎star 项目演示地址 showImg(https://segment...

    fantix 评论0 收藏0
  • 使用Vue CLI创建typescript项目

    摘要:于是搜了下原因,原来是创建时候的默认源配置导致,安装报错问题解决所以修改下刚才生成的下的属性值为就可以了再次安装成功原文 使用最新的Vue CLI @vue/cli创建typescript项目,使用vue -V查看当前的vue cli版本 安装命令 npm install -g @vue-cli 创建项目 vue create my-vue-typescript showImg(htt...

    gaomysion 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<