代码编织梦想

JS 内置的原始类型在 TypeScript 中它们都有对应的类型注解。其中,除了 null 与 undefined 以外,余下的类型对应 JavaScript 中的数据类型概念。

🍽️ null 与 undefined

在 TypeScript 中,null 与 undefined 类型都是有具体意义的类型
这两者在没有开启 strictNullChecks 检查的情况下,会被视作其他类型的子类型

🥚 void

在 TypeScript 中的 void 和 JavaScript 中的 void 不一样。void 用于描述函数没有显式 return 返回值,可以认为 void 表示一个空类型(null 与 undefined 都是具有意义的实际类型)。

🍻 type 与 interface

interface 用来描述对象、类的结构,而类型别名用来将一个函数签名、一组联合类型、一个工具类型等等抽离成一个完整独立的类型

🍢 object、Object 以及 { }

  • Object,JS 原型链的顶端是 Object 以及 Function,这也就意味着所有的原始类型与对象类型最终都指向 Object,在 TypeScript 中就表现为 Object 包含了所有的类型:
// 对于 undefined、null、void 0 ,需要关闭 strictNullChecks
const tmp1: Object = undefined;
const tmp2: Object = null;
const tmp3: Object = void 0;

const tmp4: Object = 'linbudu';
const tmp5: Object = 599;
const tmp6: Object = { name: 'linbudu' };
const tmp7: Object = () => {};
const tmp8: Object = [];

和 Object 类似的还有 Boolean、Number、String、Symbol,这几个装箱类型(Boxed Types) 同样包含了一些超出预期的类型。以 String 为例,它同样包括 undefined、null、void,以及代表的 拆箱类型(Unboxed Types) string,但并不包括其他装箱类型对应的拆箱类型,如 boolean 与 基本对象类型。
在任何情况下,你都不应该使用这些装箱类型。

  • object 的引入就是为了解决对 Object 类型的错误使用,它代表所有非原始类型的类型,即数组、对象与函数类型这些
const tmp17: object = undefined;
const tmp18: object = null;
const tmp19: object = void 0;

const tmp20: object = 'linbudu';  // X 不成立,值为原始类型
const tmp21: object = 599; // X 不成立,值为原始类型

const tmp22: object = { name: 'linbudu' };
const tmp23: object = () => {};
const tmp24: object = [];
  • {},一个空对象,可以认为{}就是一个对象字面量类型(对应到字符串字面量类型这样)。你可以认为使用{}作为类型签名就是一个合法的,但内部无属性定义的空对象,这类似于 Object(想想 new Object()),它意味着任何非 null / undefined 的值:
const tmp25: {} = undefined; // 仅在关闭 strictNullChecks 时成立,下同
const tmp26: {} = null;
const tmp27: {} = void 0; // void 0 等价于 undefined

const tmp28: {} = 'linbudu';
const tmp29: {} = 599;
const tmp30: {} = { name: 'linbudu' };
const tmp31: {} = () => {};
const tmp32: {} = [];

虽然能够将其作为变量的类型,但你实际上无法对这个变量进行任何赋值操作

image.png

🍥 字面量类型

字面量类型主要包括字符串字面量类型数字字面量类型布尔字面量类型对象字面量类型,它们可以直接作为类型标注。它代表着比原始类型更精确的类型,同时也是原始类型的子类型。它通常和联合类型(即这里的 |)一起使用,表达一组字面量类型。

例子:

interface Tmp {
  mixed: true | string | 599 | {} | (() => {}) | (1 | 2)
}

这里有几点需要注意的:

  • 对于联合类型中的函数类型,需要使用括号()包裹起来
  • 函数类型并不存在字面量类型,因此这里的 (() => {}) 就是一个合法的函数类型
  • 你可以在联合类型中进一步嵌套联合类型,但这些嵌套的联合类型最终都会被展平到第一级中

对象字面量类型

对象字面量类型就是一个对象类型的值。当然,这也就意味着这个对象的值全都为字面量值:

interface Tmp {
  obj: {
    name: "linbudu",
    age: 18
  }
}

const tmp: Tmp = {
  obj: {
    name: "linbudu",
    age: 18
  }
}

需要注意的是,无论是原始类型还是对象类型的字面量类型,它们的本质都是类型而不是值。它们在编译时同样会被擦除,同时也是被存储在内存中的类型空间而非值空间。
如果说字面量类型是对原始类型的进一步扩展,那么枚举在某些方面则可以理解为是对对象类型的扩展。

🍭 枚举

如果要和 JavaScript 中现有的概念对比,最贴切的可能就是曾经写过的 constants 文件了。

enum PageUrl {
  Home_Page_Url = "url1",
  Setting_Page_Url = "url2",
  Share_Page_Url = "url3",
}

const home = PageUrl.Home_Page_Url;

这么做的好处非常明显。首先,你拥有了更好的类型提示。其次,这些常量被真正地约束在一个命名空间下。

枚举和对象的重要差异在于,对象是单向映射的,我们只能从键映射到键值。而枚举是双向映射的,即你可以从枚举成员映射到枚举值,也可以从枚举值映射到枚举成员:

enum Items {
  Foo,
  Bar,
  Baz
}

const fooValue = Items.Foo; // 0
const fooKey = Items[0]; // "Foo"

要了解这一现象的本质,我们需要来看一看枚举的编译产物,如以上的枚举会被编译为以下 JavaScript 代码:

"use strict";
var Items;
(function (Items) {
    Items[Items["Foo"] = 0] = "Foo";
    Items[Items["Bar"] = 1] = "Bar";
    Items[Items["Baz"] = 2] = "Baz";
})(Items || (Items = {}));

obj[k] = v 的返回值即是 v,因此这里的 obj[obj[k] = v] = k 本质上就是进行了 obj[k] = vobj[v] = k 这样两次赋值。

但需要注意的是,仅有值为数字的枚举成员才能够进行这样的双向枚举,字符串枚举成员仍然只会进行单次映射

除了数字枚举与字符串枚举这种分类以外,其实还存在着普通枚举与常量枚举这种分类方式。

常量枚举和枚举相似,只是其声明多了一个 const:

const enum Items { Foo, Bar, Baz } 
const fooValue = Items.Foo; // 0

它和普通枚举的差异主要在访问性与编译产物。对于常量枚举,你只能通过枚举成员访问枚举值(而不能通过值访问成员)。同时,在编译产物中并不会存在一个额外的辅助对象(如上面的 Items 对象),对枚举成员的访问会被直接内联替换为枚举的值。以上的代码会被编译为如下形式:

const fooValue = 0 /* Foo */; // 0

实际上,常量枚举的表现、编译产物还受到配置项 --isolatedModules 以及 --preserveConstEnums 等的影响,我们会在后面的 TSConfig 详解中了解更多。

🪖 函数

函数重载签名

拥有多个重载声明的函数在被调用时,是按照重载的声明顺序往下查找。

function func(foo: number, bar: true): string;
function func(foo: number, bar?: false): number;
function func(foo: number, bar?: boolean): string | number {
  if (bar) {
    return String(foo);
  } else {
    return foo * 599;
  }
}

异步函数、Generator 函数等类型签名

async function asyncFunc(): Promise<void> {}
function* genFunc(): Iterable<void> {}
async function* asyncGenFunc(): AsyncIterable<void> {}

🐸 Class

访问符:public / private / protected / readonly,protected:此类成员仅能在类与子类中被访问。

静态成员

class Foo {
  static staticHandler() { }
  public instanceHandler() { }
}

翻译成es5

var Foo = /** @class */ (function () {
    function Foo() {}
    // 静态成员不处于原型链
    Foo.staticHandler = function () { };
    // 方法和属性处于原型链
    Foo.prototype.instanceHandler = function () { };
    return Foo;
}());

静态成员直接被挂载在函数体上,而实例成员挂载在原型上

静态成员不会被实例继承,它始终只属于当前定义的这个类(以及其子类)。而原型对象上的实例成员则会沿着原型链进行传递,也就是能够被继承。

Extend

class Base { }

class Derived extends Base { }

派生类中可以访问到使用 publicprotected 修饰符的基类成员。基类中的方法也可以在派生类中被覆盖。

但仍然可以通过 super 访问到基类中的方法:

class Base {
  print() { }
}

class Derived extends Base {
  print() {
    super.print()
    // ...
  }
}

在派生类中覆盖基类方法时,并不能确保派生类的这一方法能覆盖基类方法,万一基类中不存在这个方法呢?
所以,TypeScript 4.3 新增了 override 关键字,来确保派生类尝试覆盖的方法一定在基类中存在定义:

class Base {
  printWithLove() { }
}

class Derived extends Base {
  override print() {
    // ...
  }
}

抽象类

抽象类是对类结构与方法的抽象。我们可以实现(implements)一个抽象类,且必须完全实现这个抽象类的每一个抽象成员。

在 TypeScript 中无法声明静态的抽象成员

抽象类和 interface 的区别

TS 的 interface 是一种规范,不存在于运行时,只存在于类型空间。

抽象类是只为了类服务的,并且在运行时也会存在,存在于值空间的类型描述与约束,它的本质是一个合法的类。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/jexxx/article/details/128816858

【cutejavascript】angular6入门项目(1.构建项目和创建路由)-爱代码爱编程

本文目录 一、项目起步二、编写路由组件 三、编写页面组件 1.编写单一组件2.模拟数据3.编写主从组件 四、编写服务 1.为什么需要服务2.编写服务 五、引入RxJS 1.关于RxJS2.引入RxJS3.改造数据获取方式 六、改造组件 1.添加历史记录组件2.添加和删除历史记录 七、HTTP改造 1.引入H

TypeScript超详细入门教程(上)-爱代码爱编程

TypeScript超详细入门教程(上)   01 开篇词:Hello~TypeScript 01 开篇词:Hello~TypeScript 更新时间:2019-10-30 13:49:46   既然我已经踏上这条道路,那么,任何东西都不应妨碍我沿着这条路走下去。——康德   同学你好,我是Lison。很高兴你对TypeScript感兴

视频教程-TypeScript极速完全进阶指南视频课程-其他-爱代码爱编程

TypeScript极速完全进阶指南视频课程 10年以上编程经验,曾主持并参与多个公司大型项目的开发,在教育机构主导前端课程研发工作,输送大批学生进入国内一线互联网公司。 刘忠彬

写给初中级前端的高级进阶指南(万字长文,建议收藏)-爱代码爱编程

前言 由于公众号文章不允许外链,需要跳转文中链接的同学可以在脚注里找到各个的资源链接,也可以通过点击阅读原文更加方便的跳转链接。 我曾经一度很迷茫,在学了 Vue、React 的实战开发和应用以后,好像遇到了一些瓶颈,不知道该怎样继续深入下去。相信这也是很多一两年经验的前端工程师所遇到共同问题,这篇文章,笔者想结合自己的一些成长经历整理出一些

七厂面经--应届小前端的破局之路-爱代码爱编程

自我介绍 双非二本,软件工程,自学前端,今年毕业。 喜欢编程,古风,日语和英语。 常以冷月心之名混迹前端江湖,也曾在混迹网文圈时用冷月心做笔名签约掌阅,作品《清起风云》,百度可查。 求职期间写了一个小博客,感兴趣的可以看看 https://lengyuexin.github.io/gatsby 为什么离职 这个问题,几乎我参加的每一场面试

写给初中级前端的高级进阶指南(万字路线)-爱代码爱编程

前言 我曾经一度很迷茫,在学了 Vue、React 的实战开发和应用以后,好像遇到了一些瓶颈,不知道该怎样继续深入下去。相信这也是很多一两年经验的前端工程师所遇到共同问题,这篇文章,笔者结合自己的一些成长经历整理出一些路线,帮助各位初中级前端工程师少走一些弯路。 本篇文章面对的人群是开发经验1到3年的初中级前端工程师。 JavaScript 原生 js

2021 字节前端面试题汇总-爱代码爱编程

自我介绍、项目介绍 (1)怎么学习前端的,看了哪些书 (2)实现左中右三栏布局,左右固定宽度,中间自适应 (3)var、 let、 const的区别(重点) (4)看代码说输出 var length = 10; function fn() { console.log(this); return this.length+1; } var obj =

写给初中级前端的高级进阶指南-爱代码爱编程

大家好,我是若川。最近组织了源码共读活动。每周读 200 行左右的源码。很多第一次读源码的小伙伴都感觉很有收获,感兴趣可以加我微信ruochuan12,拉你进群学习。 前言 我曾经一度很迷茫,在学了 Vue、React 的实战开发和应用以后,好像遇到了一些瓶颈,不知道该怎样继续深入下去。相信这也是很多一两年经验的前端工程师所遇到共同问题,

学习技术要执着但也不能太执着-爱代码爱编程

作为程序员,我们会用到很多的技术,这些技术涉及到不同的领域,而每一个领域都有很大的可以深挖的空间,那我们学习的时候怎么在深度和广度的做抉择呢? 我的观点是在一个领域持续深入,成为这个领域的专家,但对其他的领域也要做一些了解,也就是成为一专多能的 T 型人才。这样既能保证较高的竞争力,也有扩展其他方面的可能性。 我们的晋升路线也是这样的,p7 的定

【TS】快速上手(一)初遇:Hello,TypeScript-爱代码爱编程

文章目录 一、学习TypeScript的意义1. 强类型 VS 弱类型2. 静态语言 VS 动态语言二、TypeScript特性三、搭建TypeScript环境 嗨!~ 大家好,我是YK菌 🐷 ,一个微系前端 ✨,爱思考,爱总结,爱记录,爱分享 🏹,欢迎关注我呀 😘 ~ [微信公众号:ykyk2012] 今天开始学习Typ

【TS】快速上手(二)类型声明-爱代码爱编程

文章目录 1. 起步2. 类型2.1 变量2.2 自动类型判断2.3 函数2.4 类型详解voidanyunknownnever对象函数数组元组 Tuple字面量2.5 联合类型2.6 类型别名2.7 总结3. 类型断言 嗨!~ 大家好,我是YK菌 🐷 ,一个微系前端 ✨,爱思考,爱总结,爱记录,爱分享 🏹,欢迎关注我呀 😘 ~ [微

成为优秀的ts体操高手 之 ts 类型体操前置知识储备_jioho_的博客-爱代码爱编程

TS 类型体操前置知识储备 如果你正在学习 TS,可是像我一样仅仅停留在定义类型,定义 interface/type 的层面的话, 这份体操类型练习题一定不要错过 ! type-challenges 写这篇文章的时候我只做完了体操类型的中等级别的题目(还有 2-3 道其实没完全解出来) 简单搭建一下做题环境 我喜欢做一题拷贝一题,所以我 clone

一名运营,自学一年前端,成功入职杭州某独角兽企业,他的面试经验和学习方法等分享...-爱代码爱编程

大家好,我是若川。这是我的微信群里小伙伴@年年 的投稿。他是19年毕业,之前做的是运营相关的工作,在我的交流群里非常活跃,自学一年前端,目前成功转行入职杭州一家独角兽企业。相信他的文章能带给大家一些启发和激励。 0 写在最前面 我是年年,于19年毕业的,之前两份工作都不是开发相关,也就是0经验转行。工作之余持续学习前端大概

大三的小白同学是如何拿到字节offer的,经验分享-爱代码爱编程

这是来自大三邵小白同学的投稿。原文链接:https://juejin.cn/post/7092806181856657445 很多时候我们容易羡慕别人成功了,却往往没有看到别人背后的努力。 1前言 大家好,我是邵小白,一个长沙某不知名双非的大三学生。今年三月份来到杭州丁香园实习,没错就是网上可以看病,然后经常被人说卖买药公司的那个。实习期