一、为什么要用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 = nullvalue = {}
那当初必定有小伙伴纳闷,诶,那它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] // 定义一个数组,外面值必须是numberconst 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}// goodenum 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]) // BLUEconsole.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 | numberconst name: typeUnite = "前端娱乐圈"const age: typeUnite = 18
1. 那么type类型别名和interface接口有什么区别呢
1. type不反对interface申明
type Types = numbertype 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 = 123type testType = typeof countconst count: number = 123interface 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 | 2const ObjJson: Record<IndexList, "前端娱乐圈"> = { 0: "前端娱乐圈", 1: "前端娱乐圈", 2: "前端娱乐圈"}
九、闲聊
给在北京通州租房小伙伴们提个醒,最近被这狗B小房地产公司坑了,租房到期成心不退押金,大家在通州找房的小伙伴们留神一下,千万别碰见这家狗中介公司,这家公司注册一堆公司名,北京珺奇地产、北京珺邺地产等,打着二十一世纪旗号成心骗人。你们必定问我为啥找这么小公司租房,特马的这里还得吐槽一下这个某居客App,我第一次用这个App租房,没想到这外面都是一堆相似于这种的小中介公司,真的很恶心。租房还得找大公司,靠谱安心。
感激
谢谢你读完本篇文章,心愿对你能有所帮忙,如有问题欢送各位斧正。
我是蛙人,如果感觉写得能够的话,请点个赞吧❤。
感兴趣的小伙伴能够退出 [ 前端娱乐圈交换群 ] 欢送大家一起来交换探讨
写作不易,「点赞」+「在看」+「转发」 谢谢反对❤
下篇更新TypeScript实战,欢送关注
参考资料
- https://www.cnblogs.com/mengf...
- 了不起的 TypeScript 入门教程
- TypeScript编程实体书
- TypeScript中文网