第一课, 体验typescriptjavascript
第三课, 泛型vue
第四课, 解读高级类型java
这一节很重要, 能够说是ts的最核心部分, 这一节学完其实就能够开始用ts写代码了, 想一想typescript中的type, 再看看标题中的"类型"2字, 因此请你们务必认真.github
由于高级类型的内容比较多, 可是有些基础类型的知识点还必需要用到高级类型的知识讲解才连贯, 因此本节课把最经常使用的高级类型提早讲解一下, 好比接口/联合类型/交叉类型.typescript
ts中基础类型有以下几种:boolean / number / string / object / 数组 / 元组 / 枚举 / any / undefined / null / void / never, 下面咱们一一举例学习:数组
补充说明: 上面列出的类型, 是ts中表示类型的关键字, 其中object
实际上是包含数组/元祖/枚举, 在ts的概念中, 这个叫作类型兼容, 就是说数组类型数据, 也能够用object来标注:微信
let array:object = [12,321];
复制代码
介绍类型前,有一个前置知识点就是字面量, 字面量的意思就是直接声明, 而非new关键词实例化出来的数据:dom
// 字面量
const n:number = 123;
const s:string = '456';
const o:object = {a:1,b:'2'};
// 非字面量
const n:Number = new Number(123);
const s:String = new String('456');
const o:Object = new Object({a:1,b:'2'});
复制代码
经过上面的例子, 你们应该看明白为何ts中有些类型的开头字母是小写的了吧. 这是由于ts中用小写字母开头的类型表明字面量, 大写的是用来表示经过new实例化的数据.
布尔类型, 取值只有true
/ false
const IS_MOBILE:boolean = true;
const IS_TABLE:boolean = false;
复制代码
数字类型, 整数/小数都包括, 同时支持2/8/10/16进制字面量.
let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
let binaryLiteral: number = 0b1010;
let octalLiteral: number = 0o744;
复制代码
字符串类型
let s1:string = 'hello world!';
let s2:string = 'hello ${name}`;
复制代码
数组有2种表示方式:
第1种, 经过在指定类型后面增长[]
, 表示该数组内的元素都是该指定类型:
let numbers:number[] = [1,2,3,4,5];
// number|string表明联合类型, 下面的高级类型中会讲
let numbers:(number|string)[] = [1,2,3,4,'5'];
复制代码
第2种, 经过泛型表示, Array<元素类型>
, 泛型会在后面课讲解, 先作了解便可:
let numbers:Array<number> = [1,2,3,4,5];
复制代码
元组类型表示一个已知元素数量和类型的数组, 各元素的类型没必要相同:
let list1:[number, string] = [1, '2', 3]; // 错误, 数量不对, 元组中只声明有2个元素
let list2:[number, string] = [1, 2]; // 错误, 第二个元素类型不对, 应该是字符串'2'
let list3:[number, string] = ['1', 2]; // 错误, 2个元素的类型颠倒了
let list4:[number, string] = [1, '2']; // 正确
复制代码
枚举是ts中有而js中没有的类型, 编译后会被转化成对象, 默认元素的值从0开始, 以下面的Color.Red
的值为0, 以此类推Color.Green
为1, Color.Blue
为2:
enum Color {Red, Green, Blue}
// 等价
enum Color {Red=0, Green=1, Blue=2}
复制代码
固然也能够本身手动赋值:
enum Color {Red=1, Green=2, Blue=4}
复制代码
而且咱们能够反向经过值获得他的键值:
enum Color {Red=1, Green=2, Blue=4}
Color[2] === 'Green' // true
复制代码
看下编译成js后的枚举代码, 你就明白为何能够反向获得键值:
var Color;
(function (Color) {
Color[Color["Red"] = 0] = "Red";
Color[Color["Green"] = 1] = "Green";
Color[Color["Blue"] = 2] = "Blue";
})(Color || (Color = {}));
// Color的值为: {0: "Red", 1: "Green", 2: "Blue", Red: 0, Green: 1, Blue: 2}
复制代码
any表明任意类型, 也就是说, 若是你不清楚变量是什么类型, 就能够用any进行标记, 好比引入一些比较老的js库, 没有声明类型, 使用的时候就能够标记为any类型, 这样ts就不会提示错误了. 固然不能全部的地方都用any, 那样ts就没有使用的意义了.
let obj:any = {};
// ts本身推导不出forEach中给obj增长了'a'和'b'字段.
['a', 'b'].forEach(letter=>{
obj[letter] = letter;
});
// 可是由于标记了any, 因此ts认为a可能存在
obj.a = 123
复制代码
void的意义和any相反, 表示不是任何类型, 通常出如今函数中, 用来标记函数没有返回值:
function abc(n:number):void{
console.log(n);
}
复制代码
void类型对应2个值, 一个是undefined,一个null:
const n1:void = undefined;
const n2:void = null;
复制代码
默认状况下null和undefined是全部类型的子类型, 好比:
const n1:null = 123;
const n2:undefined = '123';
复制代码
注意: 这是由于默认状况下的编译选项strictNullChecks为false, 可是为了不一些奇怪的问题出现, 我仍是建议你们设置为true(编译选项设置的内容, 会在后面的课程讲解), 请用精准的类型去标注.
若是一个变量的值确实须要是null
或者undefined
, 能够像下面这么用, ts会自动根据if/else
推导出正确类型:
// 这是"联合类型", 在"高级类型"中会有详细介绍, 表示n多是undefined也多是number
let num: undefined|number;
if(Math.random()>0.5) num = 1;
if(undefined !== num) {
num++;
}
复制代码
never表示不可达, 用文字还真很差描述, 主要使用在throw
的状况下:
function error():never{
throw '错了!';
}
复制代码
object表示非原始类型, 也就是除number/ string/ boolean/ symbol/ null/ undefined以外的类型:
let o1:object = [];
let o2:object = {a:1,b:2};
复制代码
可是, 咱们实际上基本不用object类型的, 由于他标注的很是不具体, 通常都用接口来标注更具体的对象类型, 请继续看下面的接口的内容.
经过基础类型组合而来的, 咱们能够叫他高级类型. 包含: 交叉类型 / 联合类型 / 接口等等, 固然不止他们3个, 为了避免让本节课太长形成读者疲劳, 本节只先讲这3个, 不过不要着急, 下节课会完结高级类型.
一种定义复杂类型的格式, 好比咱们用对象格式存储一篇文章, 那么就能够用接口定义文章的类型:
interface Article {
title: stirng;
count: number;
content:string;
fromSite: string;
}
const article: Article = {
title: '为vue3学点typescript(2), 类型',
count: 9999,
content: 'xxx...',
fromSite: 'baidu.com'
}
复制代码
在这种状况下,当咱们给article
赋值的时候, 若是任何一个字段没有被赋值或者字段对应的数据类型不对, ts都会提示错误, 这样就保证了咱们写代码不会出现上述的小错误.
仍是上面的例子, fromSite
的意思是文章来自那个网站,若是文章都是原创的, 该字段就不会有值, 可是若是咱们不传又会提示错误, 怎么办? 这时候就须要标记fromSite
字段为非必填, 用"?"标记:
interface Article {
title: stirng;
count: number;
content:string;
fromSite?: string; // 非必填
}
// 不会报错
const article: Article = {
title: '为vue3学点typescript(2), 类型',
count: 9999,
content: 'xxx...',
}
复制代码
接口不只能够定义对象, 还能够定义函数:
// 声明接口
interface Core {
(n:number, s:string):[number,string]
}
// 声明函数遵循接口定义
const core:Core = (a,b)=>{
return [a,b];
}
复制代码
先简单看下如何给类定义接口, 后面的课程具体讲类:
// 定义
interface Animate {
head:number;
body:number;
foot:number;
eat(food:string):void;
say(word:string):string;
}
// implements
class Dog implements Animate{
head=1;
body=1;
foot=1;
eat(food:string){
console.log(food);
}
say(word:string){
return word;
}
}
复制代码
交叉类型是将多个类型合并为一个类型, 表示"而且"的关系,用&
链接多个类型, 经常使用于对象合并:
interface A {a:number};
interface B {b:string};
const a:A = {a:1};
const b:B = {b:'1'};
const ab:A&B = {...a,...b};
复制代码
联合类型也是将多个类型合并为一个类型, 表示"或"的关系,用|
链接多个类型:
function setWidth(el: HTMLElement, width: string | number) {
el.style.width = 'number' === typeof width ? `${width}px` : width;
}
复制代码
注意: 我这里标记了el为HTMLElement, 能够在typescript的仓库看到ts还定义了不少元素, 请自行浏览(不用背, 用的时候现查), github.com/microsoft/T…
若是您看完了上面的全部知识点, 你就能够开始动手造轮子练习了, 加油. 下面是我用ts造的轮子, 若是喜欢请帮忙点下star, 谢谢.
命令式调用vue组件: github.com/any86/vue-c…
工做中经常使用的一些代码片断: github.com/any86/usefu…
一个mini的事件管理器: github.com/any86/any-e…
感谢你们的阅读, 若有疑问能够加群🚀, 群里有好多有趣的前端的小伙伴, 让咱们共同窗习成长吧!
也可加我微信, 我拉你进入微信群(因为腾讯对微信群的100人限制, 超过100人后必须由我拉进去)