共计 16369 个字符,预计需要花费 41 分钟才能阅读完成。
一、为什么要用 TypeScript
TypeScript
能够让咱们开发中防止一些 类型
或者 一些不是咱们预期心愿的代码后果
谬误。xxx is not defined 咱们都晓得 JavaScript
谬误是在运行中才抛出的,然而 TypeScript
谬误间接是在编辑器里告知咱们的,这极大的晋升了开发效率,也不必花大量的工夫去写单测,同时也防止了大量的工夫排查Bug
。
二、TypeScript 优缺点
长处
- 个别咱们在前后端联调时,都要去看接口文档上的字段类型,而
TypeScript
会主动帮咱们辨认以后的类型。节俭了咱们去看文档
或者network
工夫。这叫做类型推导(待会咱们会讲到) - 敌对地在编辑器里提醒谬误,防止代码在运行时类型隐式转换踩坑。
毛病
- 有肯定的学习老本,
TypeScript
中有几种类型概念,interface 接口
、class 类
、enum 枚举
、generics 泛型
等这些须要咱们花工夫学习。 - 可能和一些插件库联合的不是很完满
三、TypeScript 运行流程及 JavaScript 代码运行流程
1. JavaScript 运行流程如下,依赖 NodeJs 环境和浏览器环境
- 将
JavaScript
代码转换为JavaScript-AST
- 将
AST
代码转换为字节码 - 运算时计算字节码
2. TypeScript 运行流程,以下操作均为 TSC 操作,三步执行完持续同上操作,让浏览器解析
- 将
TypeScript
代码编译为TypeScript-AST
- 查看
AST
代码上类型查看 - 类型查看后,编译为
JavaScript
代码 JavaScript
代码转换为JavaScript-AST
- 将
AST
代码转换为字节码 - 运算时计算字节码
四、TypeScript 和 JavaScript 区别
只有搞懂了二者的区别,咱们才能够更好的了解TypeScript
类型零碎个性 | JavaScript | TypeScript |
---|---|---|
类型是如何绑定? | 动静 | 动态 |
是否存在类型隐式转换? | 是 | 否 |
何时查看类型? | 运行时 | 编译时 |
何时报告谬误 | 运行时 | 编译时 |
类型绑定
JavaScript
JavaScript
动静绑定类型,只有运行程序能力晓得类型,在程序运行之前 JavaScript
对类型无所不知
TypeScript
TypeScript
是在程序运行前(也就是编译时)就会晓得以后是什么类型。当然如果该变量没有定义类型,那么 TypeScript
会主动类型推导进去。
类型转换
JavaScript
比方在 JavaScript
中1 + true
这样一个代码片段,JavaScript
存在隐式转换,这时 true
会变成 number
类型 number(true)
和 1 相加。
TypeScript
在 TypeScript
中,1+true
这样的代码会在 TypeScript
中报错,提醒 number
类型不能和 boolean
类型进行运算。
何时查看类型
JavaScript
在 JavaScript
中只有在程序运行时能力查看类型。类型也会存在隐式转换,很坑。
TypeScript
在 TypeScript
中,在编译时就会查看类型,如果和预期的类型不合乎间接会在编辑器里报错、爆红
何时报告谬误
JavaScript
在 JavaScript
只有在程序执行时能力抛出异样,JavaScript
存在隐式转换,等咱们程序执行时能力真正的晓得代码类型是否是预期的类型,代码是不是无效。
TypeScript
在TypeScript 中
,当你在编辑器写代码时,如有谬误则会间接抛出异样,极大得进步了效率,也是不便。
五、TypeScript 总共围绕两种模式开展
显式注解类型
举个栗子
let name: string = "前端娱乐圈";
let age: number = 38;
let hobby: string[] = ["write code", "玩游戏"]
显式注解类型就是,申明变量时定义上类型(官网话语就是 申明时带上注解 ),让咱们一看就明确,哦~,这个name
是一个 string
类型。
推导类型
举个栗子
let name = "前端娱乐圈"; // 是一个 string 类型
let age = 38; // 是一个 number 类型
let hobby = ["write code", "玩游戏"] // 是一个 string 数组类型
推导类型就是去掉显示注解,零碎主动会辨认以后值是一个什么类型的。
六、装置 TypeScript && 运行
typescript
全局装置 typescript
环境。
npm i -g typescript
可是这只是装置了 typescript
,那咱们怎么运行.ts
文件呢,装置完 typescript
咱们就能够执行 tsc
命令。
如:咱们的文件叫做 index.ts
,间接在命令行执行tsc index.ts
即可。而后就能够看到在目录下编译进去一个 index.js
,这就是tsc
编译完的后果。
index.ts
const userName: string = "前端娱乐圈"
运行 tsc index.ts
,你能够看见在index.ts
的同级下又生成一个index.js
,如下就是编译的后果文件index.js
。
var userName = "前端娱乐圈"
下面咱们晓得了运行 tsc
命令就能够编译生成一个文件,有的小伙伴感觉这样太麻烦了,每次运行只是编译进去一个文件还不是运行,还得用 node index.js
才能够运行。不急咱们接着往下看
ts-node
咱们来看一下这个插件 ts-node
,这个插件能够间接运行.ts
文件,并且也不会编译进去 .js
文件。
npm i ts-node
// 运行 ts-node index.ts
讲到这里咱们理解了 为什么要用 TypeScript和它的 优缺点 以及它的 运行工作形式。
那么接下来步入 TypeScript
基础知识的陆地啦~,follow me。
感觉有帮忙的小伙伴能够关注一下:前端娱乐圈 公众号,谢谢啦~,每天更新一篇小技巧
七、基础知识
1. 根底动态类型
在 TypeScript
中根底类型跟咱们 JavScript
中根底类型是一样的。只是有各别是 Ts
外面新出的。
1. number
const count: number = 18; // 显示注解一个 number 类型
const count1 = 18; // 不显示注解,ts 会主动推导进去类型
2. string
const str: string = "前端娱乐圈"; // 显示注解一个 string 类型
const str1 = "蛙人"; // 不显示注解,ts 会主动推导进去类型
3. boolean
const status: string = false; // 显示注解一个 string 类型
const status1 = true; // 不显示注解,ts 会主动推导进去类型
4. null
const value: null = null;
const value: null = undefined; // 这一点 null 类型能够赋值 undefined 跟在 js 中是一样的,null == undefined
5. undefined
const value: undefined = undefined;
const value: undefined = null; // 这一点 null 类型能够赋值 undefined 跟在 js 中是一样的,null == undefined
6. void
预计到这有一些小伙伴可能对 void
这个比拟生疏,认为只有 TypeScript
才有的。其实不是哈,在咱们 JavaScript
就曾经存在 void
关键字啦,它的意思就是有效的,有的小伙伴可能看见过早些我的项目外面 <a href="javascript: void(0)">
这是管制 a
标签的跳转默认行为。你不管怎么执行 void
办法它都是返回undefined
那么在咱们 TypeScript
中void
类型是什么呢。它也是代表有效的,个别只用在 函数 上,通知他人这个 函数 没有返回值。
function fn(): void {} // 正确
function testFn(): void {return 1; // 报错,不承受返回值存在}
function fn1(): void { return undefined} // 显示返回 undefined 类型,也是能够的
function fn2(): void { return null} // 显示返回 null 类型也能够,因为 null == undefined
7. never
never
一个永远不会有值的类型 或者也能够说 一个永远也执行不完的类型 ,代表用于不会有值,undefined
、null
也算做是值。个别这个类型就不会用到,也不必。大家晓得这个类型就行。
const test: never = null; // 谬误
const test1: never = undefined // 谬误
function Person(): never { // 正确,因为死循环了,始终执行不完
while(true) {}}
function Person(): never { // 正确,因为递归,永远没有进口
Person()}
function Person(): never { // 正确 代码报错了,执行不上来
throw new Error()}
8. any
any
这个类型代表 任何的 、 任意的 。心愿大家在我的项目中,不要大片定义any
类型。尽管它真的好使,那这样咱们写 TypeScript
就没有任何意义了。
let value: any = ""; // 正确
value = null // 正确
value = {} // 正确
value = undefined // 正确
9. unknown
unknown
类型是咱们 TypeScript
中第二个 any
类型,也是承受任意的类型的值。它的英文翻译过去就是 未知的,咱们来看一下栗子
let value: unknown = ""
value = 1;
value = "fdsfs"
value = null
value = {}
那当初必定有小伙伴纳闷,诶,那它 unknown
相当于是 any
类型,那二者的区别是什么。咱们来看一下
let valueAny: any = "";
let valueUnknown: unknown = "";
valueAny = "蛙人";
valueUnknown = "前端娱乐圈"
let status: null = false;
status = valueAny; // 正确
status = valueUnknown // 报错,不能将 unknown 类型调配给 null 类型
咱们来看一下下面的,为什么 any
类型就能被赋值胜利,而 unknown
类型不行呢,从它俩的意义来上看,还是有点区别的,any
任何的,任意的、unknown
未知的。所以你给 unknown
类型赋值任何类型都没关系,因为它原本就是未知类型嘛。然而你如果把它的 unknown
类型去被赋值一个 null
类型,这时人家 null
这边不干了,我不承受 unknown
类型。
说白了一句话,他人不承受 unknown
类型,而 unknown
类型承受他人,哈哈哈哈。
2. 对象动态类型
说起对象类型,咱们必定都能想到对象蕴含 {}
、 数组
、 类
、函数
1. object && {}
其实这俩意思一样,{}
、object
示意非原始类型,也就是除 number
,string
,boolean
,symbol
,null
或undefined
之外的类型。
const list: object = {} // 空对象
const list1: object = null; // null 对象
const list: object = [] // 数组对象
const list: {} = {}
list.name = 1 // 报错 不可更改外面的字段,然而能够读取
list.toString()
2. 数组
const list: [] = []; // 定义一个数组类型
const list1: number[] = [1,2] // 定义一个数组,外面值必须是 number
const list2: object[] = [null, {}, []] // 定义一个数组外面必须是对象类型的
const list3: Array<number> = [1,2,3] // 泛型定义数组必须是 number 类型,泛型咱们待会讲到
3. 类
// 类
class ClassPerson = {name: "前端娱乐圈"}
const person: ClassPerson = new Person();
person.xxx = 123; // 这行代码报错,因为以后类中不存在该 xxx 属性
4. 函数
// 函数
const fn: () => string = () => "前端娱乐圈" // 定义一个变量必须是函数类型的,返回值必须是 string 类型
3. 函数类型注解
这里说一下函数显示注解和函数参数不会类型推导问题。
1. 函数返回类型为 number
function fn(a, b): number {return a + b;}
fn(1, 2)
2. 函数 void
显示注解为 void
类型,函数没有返回值。
function fn(): void {console.log(1)
}
3. 函数不会主动类型推导
能够看到上面的函数类型,不会主动类型推导,咱们实参尽管传入的 1 和 2,然而形参方面是能够承受任意类型值的,所以零碎也辨认不进去你传递的什么,所以这里得须要咱们显示定义注解类型。
function testFnQ(a, b) {return a + b}
testFnQ(1,2)
咱们来革新一下。
function testFnQ(a:number, b:number) {return a + b}
testFnQ(1,2)
咱们再来看一下参数对象显示注解类型,也是在 :
号前面赋值每个字段类型即可。
function testFnQ(obj : {num: number}) {return obj.num}
testFnQ({num: 18})
4. 元组 Tuple
元组用于示意一个已知数组的数量和类型的数组,定义数组中每一个值的类型,个别不常常应用。
const arr: [string, number] = ["前端娱乐圈", 1]
const arr: [string, string] = ["前端娱乐圈", 1] // 报错
5. 枚举 Enum
Enum
枚举类型,能够设置默认值,如果不设置则为索引。
enum color {
RED,
BLUE = "blue",
GREEN = "green"
}
// color["RED"] 0
// color["BLUE"] blue
像下面的 color
中RED 没
有设置值,那么它的值则为 0
,如果BLUE
也不设置的话那么它的值则是1
,它们这里是递增。如果设置值则是返回设置的值
留神这里还有一个问题,间接来上代码
通过下面学习咱们晓得了 enum
能够递增值,也能够设置默认值。然而有一点得留神一下,enum
没有 json
对象那样灵便,enum
不能在任意字段上设置默认值。
比方上面栗子,RED
没有设置值,而后 BLUE
设置了默认值,然而 GREEN
又没有设置,这时这个 GREEN
会报错。因为你第二个 BLUE
设置完默认值,第三又不设置,这时代码都不晓得该咋递增了,所以报错。还有一种计划就是你给 BLUE
能够设置一个数字值,这时第三个 GREEN
不设置也会跟着递增,因为都是 number
类型。
// 报错
enum color {
RED,
BLUE = "blue",
GREEN
}
// good
enum color {
RED, // 0
BLUE = 4, // 4
GREEN // 5
}
比方 enum
枚举类型还能够反差,通过 value
查key
值。像咱们 json
对象就是不反对这种写法的。
enum color {
RED, // 0
BLUE = 4, // 4
GREEN // 5
}
console.log(color[4]) // BLUE
console.log(color[0]) // RED
5. 接口 Interface
接口 interface
是什么,接口 interface
就是不便咱们定义一处代码,多处复用。接口外面也存在一些修饰符。上面咱们来认识一下它们吧。
1. 接口怎么复用
比方在讲到这之前,咱们不晓得 接口
这货色,可能须要给对象定义一个类型的话,你可能会这样做。
const testObj: {name: string, age: number} = {name: "前端娱乐圈", age: 18}
const testObj1: {name: string, age: number} = {name: "蛙人", age: 18}
咱们用接口来革新一下。
interface Types {
name: string,
age: number
}
const testObj: Types = {name: "前端娱乐圈", age: 18}
const testObj1: Types = {name: "蛙人", age: 18}
能够看到应用 interface
关键字定义一个接口,而后赋值给这两个变量,实现复用。
2. readonly 修饰符
readonly
类型,只可读状态,不可更改。
interface Types {
readonly name: string,
readonly age: number
}
const testObj: Types = {name: "前端娱乐圈", age: 18}
const testObj1: Types = {name: "蛙人", age: 18}
testObj.name = "张三" // 无奈更改 name 属性,因为它是只读属性
testObj1.name = "李四" // 无奈更改 name 属性,因为它是只读属性
3. ? 可选修饰符
可选修饰符以 ?
定义,为什么须要可选修饰符呢,因为如果咱们不写 可选修饰符
,那interface
外面的属性都是必填的。
interface Types {
readonly name: string,
readonly age: number,
sex?: string
}
const testObj: Types = {name: "前端娱乐圈", age: 18}
4. extends 继承
咱们的 interface
也是能够继承的,跟 ES6Class
类一样,应用 extends
关键字。
interface Types {
readonly name: string,
readonly age: number,
sex?: string
}
interface ChildrenType extends Types { // 这 ChildrenType 接口就曾经继承了父级 Types 接口
hobby: []}
const testObj: ChildrenType = {name: "前端娱乐圈", age: 18,hobby: ["code", "羽毛球"] }
5. propName 扩大
interface 外面这个性能就很弱小,它能够写入不在 interface 外面的属性。
interface Types {
readonly name: string,
readonly age: number,
sex?: string,
}
const testObj: Types = {name: "前端娱乐圈", age: 19, hobby: [] }
下面这个 testObj
这行代码会爆红,因为 hobby
属性不存在 interface
接口中,那么咱们不存在的接口中的,还不让人家写了?。这时候能够应用 自定义 就是下面的propName
。
interface Types {
readonly name: string,
readonly age: number,
sex?: string,
[propName: string]: any // propName 字段必须是 string 类型 or number 类型。值是 any 类型,也就是任意的
}
const testObj: Types = {name: "前端娱乐圈", age: 19, hobby: [] }
在运行下面代码,就能够看到不爆红了~
6. Type
咱们再来看一下 Type
,这个是申明类型别名使的,别名类型只能定义是: 根底动态类型
、 对象动态类型
、 元组
、 联结类型
。
留神:type 别名不能够定义 interface
type Types = string;
type TypeUnite = string | number
const name: typeUnite = "前端娱乐圈"
const age: typeUnite = 18
1. 那么 type 类型别名和 interface 接口有什么区别呢
1. type 不反对 interface 申明
type Types = number
type Types = string // 报错,类型别名 type 不容许呈现反复名字
interface Types1 {name: string}
interface Types1 {age: number}
// interface 接口能够呈现反复类型名称,如果反复呈现则是,合并起来也就是变成 {name:string, age: number}
第一个 Types
类型别名 type 不容许呈现反复名字,interface 接口能够呈现反复类型名称,如果反复呈现则是,合并起来也就是变 {name:string, age: number}
再来看一下 interface 另一种状况
interface Types1 {name: string}
interface Types1 {name: number}
能够看到下面两个同名称的 interface
接口,外面的属性也是同名称,然而类型不一样。这第二个的 Types1
就会爆红,提醒:后续申明的接口,必须跟后面申明的同名属性类型必须保持一致 ,把后续申明的name
它类型换成 string
即可。
2. type 反对表达式 interface 不反对
const count: number = 123
type testType = typeof count
const count: number = 123
interface testType {[name: typeof count]: any // 报错
}
能够看到下面 type
反对表达式,而 interface
不反对
3. type 反对类型映射,interface 不反对
type keys = "name" | "age"
type KeysObj = {[propName in keys]: string
}
const PersonObj: KeysObj = { // 失常运行
name: "蛙人",
age: "18"
}
interface testType {[propName in keys]: string // 报错
}
7. 联结类型
联结类型
用|
示意,说白了就是满足其中的一个 类型
就能够。
const statusTest: string | number = "前端娱乐圈"
const flag: boolean | number = true
再来看一下栗子。咱们用函数参数应用 联结类型 看看会产生什么
function testStatusFn(params: number | string) {console.log(params.toFixed()) // 报错
}
testStatusFn(1)
下面咱们说过了,函数参数类型不能类型主动推导,更何况当初用上 联结类型,零碎更懵逼了,不能辨认以后实参的类型。所以拜访以后类型上的办法报错。
接下来带大家看一些 类型爱护
,听着挺高级,其实这些大家都见过。别忘了记得关注: 前端娱乐圈 公众号哦,嘻嘻
1. typeof
function testStatusFn(params: number | string) {console.log(params.toFixed()) // 报错
}
testStatusFn(1)
革新后
// 失常
function testStatusFn(params: string | number) {if (typeof params == "string") {console.log(params.split)
}
if (typeof params == "number") {console.log(params.toFixed)
}
}
testStatusFn(1)
2. in
// 报错
interface frontEnd {name: string}
interface backEnd {age: string}
function testStatusFn(params: frontEnd | backEnd) {console.log(params.name)
}
testStatusFn({name: "蛙人"})
革新后
// 失常
function testStatusFn(params: frontEnd | backEnd) {if ("name" in params) {console.log(params.name)
}
if ("age" in params) {console.log(params.age)
}
}
testStatusFn({name: "蛙人"})
3. as 断言
// 报错
interface frontEnd {name: string}
interface backEnd {age: string}
function testStatusFn(params: frontEnd | backEnd) {console.log(params.name)
}
testStatusFn({name: "蛙人"})
革新后
// 失常
function testStatusFn(params: frontEnd | backEnd) {if ("name" in params) {const res = (params as frontEnd).name
console.log(res)
}
if ("age" in params) {const res = (params as backEnd).age
console.log(res)
}
}
testStatusFn({age: 118})
8. 穿插类型
穿插类型
就是跟联结类型相同,它用 &
示意,穿插类型
就是两个类型必须存在。这里还用下面的 联结类型 的栗子来看下。
interface frontEnd {name: string}
interface backEnd {age: number}
function testStatusFn(params: frontEnd & backEnd) {}
testStatusFn({age: 118, name: "前端娱乐圈"})
这里咱们能够看到实参必须传入两个 接口 (interface) 全副的属性值才能够。联结类型 是传入其中类型就能够。
留神:咱们的接口 interface 呈现同名属性
interface frontEnd {name: string}
interface backEnd {name: number}
function testStatusFn(params: frontEnd & backEnd) {console.log(params)
}
testStatusFn({name: "前端"})
下面咱们两个接口类型中都呈现了同名属性,然而类型不一样,这时类型就会变为never
。
<img src=”https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/51e337707b6641e590bbb0139fabacdb~tplv-k3u1fbpfcp-watermark.image” width=”90%”>
9. 泛型
泛型是 TypeScript
中最难了解的了,这里我尽量用通俗易懂的形式讲明确。
function test(a: string | number, b: string | number) {console.log(a, b)
}
test(1, "前端娱乐圈")
比方下面栗子,函数参数 注解类型
定义 string
和number
,调用函数实参传入也没什么问题,然而有个需要,就是实参咱们 必须传入同样的类型 (传入两个number
类型)。尽管下面这种 联结类型 也能够实现,然而如果咱们要在加一个 boolean
类型,那么 联结类型 还得在追加一个boolean
,那这样代码太冗余了。
这时就须要用到 泛型 了,泛型 是专门针对不确定的类型应用,并且灵便。泛型的应用大部分都是应用 <T>
,当然也能够轻易应用,如:<Test>
、<Custom>
都能够。
function test<T>(a: T, b: T) {console.log(a, b)
}
test<number>(1, "前端娱乐圈") // 调用前面跟着尖括号这就是泛型的类型,这时报错,因为在调用的应用类型是 number,所以只能传入雷同类型的
test<boolean>(true, false)
test<string>("前端娱乐圈", "蛙人")
下面这应用 泛型 就解决了咱们方才说的传入同一个类型参数问题,然而 泛型 也能够应用不同的参数,能够把调用类型定义为<any>
function test<T>(a: T, b: T) {console.log(a, b)
}
test<any>(1, "前端娱乐圈")
然而下面这种又有一种问题,它能够传入对象,然而如果咱们只心愿传入 number
类型和 string
类型。那么咱们 泛型 也给咱们提供了 束缚
类型。泛型 应用 extends
进行了 类型束缚 ,只能抉择string
、number
类型。
function test<T extends number | string, Y extends number | string>(a: T, b: Y) {console.log(a, b)
}
test<number, string>(18, "前端娱乐圈")
test<string, number>("前端娱乐圈", 18)
这时,传入泛型时应用 ,
逗号分隔,来定义每一个类型心愿是什么。记住,只有咱们不确定的类型,能够应用泛型。
10. 模块
TypeScript
也反对 import
和export
这里大多数小伙伴都晓得,这里都不多讲啦。
// 导入
import xxx, {xxx} from "./xxx"
// 导出
export default {}
export const name = "前端娱乐圈"
如有不明确的小伙伴,能够看我以前文章 聊聊什么是 CommonJs 和 Es Module 及它们的区别
11. Class 类
以下这三个修饰符是在
TypeScript
类中能力应用,在JavaScript
类中是不反对的。
1. public
public
为 类
的公共属性,就是不论在 类
的外部还是内部,都能够拜访该 类
中 属性 及办法 。默认定义的 属性 及办法 都是public
。
class Person {
name = "前端娱乐圈";
public age = 18;
}
const res = new Person();
console.log(res.name, res.age) // 前端娱乐圈 18
下面能够看到打印后果都能显示进去,name
属性没有定义 public
公共属性,所以 类
外面定义的 属性 及办法 默认都是 public
定义。
2. private
private
为 类
的公有属性,只有在以后 类
外面能力拜访,以后 类
就是 {}
外面区域内。在 {}
里面是不能拜访 private
定义的 属性 及办法 的
class Person {
private name = "前端娱乐圈";
private age = 18;
}
const res = new Person();
console.log(res.name, res.age) // 这俩行会爆红,以后属性为公有属性,只能在类外部拜访
class Scholl extends Person {getData() {return this.username + "," + this.age}
}
const temp = new Scholl()
console.log(temp.getData()) // 爆红~,尽管继承了 Person 类,然而 private 定义是只能在以后类拜访,子类也不能拜访。
3. protected
protected
为 类
的爱护属性,只有在 以后类 和子类 能够拜访。也就是说用 protected
属性定义的 子类 也能够拜访。
class Person {
protected username = "前端娱乐圈";
protected age = 18;
}
const res = new Person();
console.log(res.name, res.age) // 这俩行会爆红,以后属性为公有属性,只能在类外部拜访
class Scholl extends Person {getData() {return this.username + "," + this.age}
}
const temp = new Scholl()
console.log(temp.getData()) // 前端娱乐圈,18。能够失常拜访父类的属性
4. implements
implements
关键字只能在 class
中应用,顾名思义,实现一个新的类,从父级或者从接口实现所有的属性和办法,如果在 PersonAll
类外面不写进去接口外面已有的属性和办法则会报错。
interface frontEnd {
name: string,
fn: () => void}
class PersonAll implements frontEnd {
name: "前端娱乐圈";
fn() {}
}
5. 抽象类
抽象类应用 abstract
关键字定义。abstract
形象办法不能实例化,如果,抽象类外面办法是形象的,那么自身的类也必须是形象的,形象办法不能写函数体。父类外面有形象办法,那么子类也必须要从新该办法。
// 抽象类
abstract class Boss {
name = "秦";
call() {} // 形象办法不能写函数体
}
class A extends Boss {call() {console.log(this.name);
console.log("A")
}
}
class B extends Boss {call() {console.log("B")
}
}
new A().call()
该抽象类应用场景,比方 A
需要或者 B
需要正好须要一个公共属性,而后自身还有一些本人的逻辑,就能够应用抽象类,抽象类只能在 TypeScript
中应用。
12. 命名空间 namespace
咱们学到当初能够看到,不晓得小伙伴们发现没有,我的项目中文件是不是不能有反复的变量(不论你是不是一样的文件还是其它文件),否则就间接爆红了。命名空间一个最明确的目标就是解决重名问题。
命名空间应用 namespace
关键字来定义,来看栗子吧。
index.ts
namespace SomeNameSpaceName {const q = {}
export interface obj {name: string}
}
下面这样,就定义好了一个命名空间,能够看到变量 q
没有写 export
关键字,这证实它是外部的变量,就算别的 .ts
文件援用它,它也不会裸露进来。而 interface
这个 obj
接口是能够被全局拜访的。
咱们在别的页面拜访以后命名空间
1. reference 引入
/// <reference path="./index.ts" />
namespace SomeNameSpaceName {
export class person implements obj {name: "前端娱乐圈"}
}
2. import
export interface valueData {name: string}
import {valueData} from "./xxx.ts"
这时应用命名空间之后齐全能够解决不同文件重名爆红问题。
13. tsConfig.json
这个 tsconfig
文件,是咱们编译 ts 文件,如何将 ts
文件编译成咱们的 js
文件。tsc -init
这个命令会生成该文件进去哈。执行完该命令,咱们能够看到根目录下会生成一个 tsconfig.json
文件,外面有一堆属性。
那么咱们怎么将 ts
文件编译成 js
文件呢,间接执行 tsc
命令能够将根目录下所有的 .ts
文件全副编译成 .js
文件输入到我的项目下。
更多配置文档,请参考官网
{// include: ["*.ts"] // 执行目录下所有的 ts 文件转换成 js 文件
// include: ["index.ts"] // 只将我的项目下 index.ts 文件转换为 js 文件
// files: ["index.ts"] // 跟 include 一样,只执行以后数组值外面的文件, 以后 files 必须写相对路径
// exclude: ["index.ts"] // exclude 就是除了 index.ts 不执行,其它都执行
compilerOptions: {
removeComments: true, // 去掉编译完 js 文件的正文
outDir: "./build", // 最终输入的 js 文件目录
rootDir: "./src", // ts 入口文件查找
}
}
八、实用类型
最初来说一下实用类型,TypeScript
规范库自带了一些实用类型。这些实用类都是不便接口 Interface
应用。这里只列举几个罕用的,更多实用类型官网
1. Exclude
从一个类型中排除另一个类型,只能是 联结类型 ,从TypesTest
类型中排除 UtilityLast
类型。
实用于:并集类型
interface UtilityFirst {name: string}
interface UtilityLast {age: number}
type TypesTest = UtilityFirst | UtilityLast;
const ObjJson: Exclude<TypesTest, UtilityLast> = {name: "前端娱乐圈"}
2. Extract
Extract
正好跟下面那个相同,这是抉择某一个可赋值的 联结类型 ,从TypesTest
类型中只抉择 UtilityLast
类型。
实用于:并集类型
interface UtilityFirst {name: string}
interface UtilityLast {age: number}
type TypesTest = UtilityFirst | UtilityLast;
const ObjJson: Extract<TypesTest, UtilityLast> = {age: 1}
3. Readonly
把数组或对象的所有属性值转换为只读的。这里只演示一下对象栗子,数组同样的写法。
实用于:对象、数组
interface UtilityFirst {name: string}
const ObjJson: Readonly<UtilityFirst> = {name: "前端娱乐圈"}
ObjJson.name = "蛙人" // 报错 只读状态
4. Partial
把对象的所有属性设置为可选的。咱们晓得 interface
只有不设置 ?
修饰符,那么对象都是必选的。这个实用类能够将属性全副转换为可选的。
实用于:对象
interface UtilityFirst {name: string}
const ObjJson: Partial<UtilityFirst> = {}
5. Pick
Pick
选择对象类型中的局部 key
值,提取进去。第一个参数 目标值
,第二个参数 联结key
实用于:对象
interface UtilityFirst {
name: string,
age: number,
hobby: []}
const ObjJson: Pick<UtilityFirst, "name" | "age"> = {
name: "前端娱乐圈",
age: 18
}
6. Omit
Omit
选择对象类型中的局部 key
值,过滤掉。第一个参数 目标值
,第二个参数 联结key
实用于:对象
interface UtilityFirst {
name: string,
age: number,
hobby: string[]}
const ObjJson: Omit<UtilityFirst, "name" | "age"> = {hobby: ["code", "羽毛球"]
}
7. Required
Required
把对象所有可选属性转换成必选属性。
实用于:对象
interface UtilityFirst {
name?: string,
age?: number,
hobby?: string[]}
const ObjJson: Required<UtilityFirst> = {
name: "蛙人",
age: 18,
hobby: ["code"]
}
8. Record
创立一个对象后果集,第一个参数则是 key
值,第二个参数则是 value
值。规定咱们只能创立这外面字段值。
实用于:对象
type IndexList = 0 | 1 | 2
const ObjJson: Record<IndexList, "前端娱乐圈"> = {
0: "前端娱乐圈",
1: "前端娱乐圈",
2: "前端娱乐圈"
}
九、闲聊
给在 北京通州 租房小伙伴们提个醒,最近被这狗 B 小房地产公司坑了,租房到期成心不退押金,大家在 通州 找房的小伙伴们留神一下,千万别碰见这家狗中介公司,这家公司注册一堆公司名,北京珺奇地产 、 北京珺邺地产 等,打着二十一世纪旗号成心骗人。你们必定问我为啥找这么小公司租房,特马的这里还得吐槽一下这个 某居客App,我第一次用这个 App 租房,没想到这外面都是一堆相似于这种的小中介公司,真的很恶心。租房还得找大公司,靠谱安心。
感激
谢谢你读完本篇文章,心愿对你能有所帮忙,如有问题欢送各位斧正。
我是蛙人,如果感觉写得能够的话,请点个赞吧❤。
感兴趣的小伙伴能够退出 [前端娱乐圈交换群] 欢送大家一起来交换探讨
写作不易,「点赞」+「在看」+「转发」谢谢反对❤
下篇更新 TypeScript 实战,欢送关注
参考资料
- https://www.cnblogs.com/mengf…
- 了不起的 TypeScript 入门教程
- TypeScript 编程实体书
- TypeScript 中文网