一、ts基本命令
安装ts
npm install typescript -g
讯享网
检查ts版本
讯享网tsc -v
将ts编译为js
tsc index.ts
初始化ts项目
讯享网tsc -init / tsc --init
二、tsconfig.json
// tsconfig.json "outDir": "./" 编译到那个目录下
实时监视ts 转为js
讯享网tsc -p tsconfig.json --watch
三、ts语法
⚠️注意:
ts中不同的ts文件,都是同一个全局变量,因此在1.ts文件中定义的num,在2.ts中不能被重复定义,所以需要使用export {}导出一个空对象,使文件独立。
1. ts中let和const
讯享网let str = "3"; // 根据初始赋值来推导出变量的类型,以后的str的类型就不能改了 // str = 2; // 报错,原因:变量在定义的时候,类型已经确定下来了,不能修改 const num = 1; // 类型为1,常量不能被修改,所以它的值就是它的类型 const num2 = 2; // 类型为2 const str1 = '123'; // 类型为123 // ts中,let和const的区别:let的类型由它定义的值的类型来确定,而const的类型就是它值的类型
2. ts的原始数据类型
ts的原始类型 => number string boolean undefined null symbol
// ts的原始类型 => number string boolean undefined null symbol let str2:string = "1"; // let str2:number = "1"; // 报错,因为它的值类型为字符串 let bool:boolean = true; let num3:number = 10; let und:undefined = undefined; let nul:null = null; let sy:symbol = Symbol('123'); // Symbol创建出来的地址永远是新的(会创建新的内存空间) // 例如:a = 123 b = 123,那么a的地址 = b的地址,而Symbol(123) != a let vo:void = undefined; // void:空,js没有该类型 // void一般用于函数 function fn():void {
// ts中,函数没有返回值,函数类型就为void } // 函数类型是undefined会报错,除非函数返回undefined function fn1():undefined {
return undefined }
3. ts的非原始类型
讯享网export {
} // ts非原始类型 object(常用) Object {} let obj:object = {
a: 1}; let arr:object = [1,2,3]; // let num:object = 20; // 报错,object不包含number类型 let obj1:Object = {
b: 1}; let arr1:Object = [1,2,3]; let num:Object = 2; // 不会报错,Object包含 let str:Object = 'hello'; let bool:Object = true; let obj2:{
} = {
b: 1}; let arr2:{
} = [1,2,3]; let num2:{
} = 2; let str2:{
} = 'hello'; let bool2:{
} = true; // {} 等效于 Object
4. 数组类型
// let arr:object = [1,2,3]; // 数组的元素一般数据类型都一致,便于处理 // 第一种写法: let arr1:number[] = [1,2,3]; // 表示该数组中【元素】的数据类型为number arr1[0] = 10; // arr1[1] = "10"; // 报错 // 第二种写法:泛型 类型参数化 let arr2:Array<number> = [10, 20, 30] arr2[0] = 10; // arr2[1] = "10"; // 报错 // 元组(不同类型的数组) let arr3:[number, number, boolean] = [10, 20, true] arr3[0] = 20 // arr3[1] = '123' // 报错 arr3[2] = false
5.联合类型
讯享网// 联合类型 | 或 let numAndStr:number|string = 10; numAndStr = 'hello'; // 1|'2' 在这里的1 和 '2‘是类型, 常量,表示numAndStr2的值只能是 1 或 '2' let numAndStr2: 1|'2' = 1 let numAndStr3: 1|'2' = '2' // let numAndStr4: 1|'2' = 2 // 报错,只能是1 或 '2'中的一个 // 表明obj必须要有a 或 b属性,并且a的类型为1,或b的类型为'3'(可以a、b都有) let obj:{
a:1}|{
b:'3'} = {
a: 1}; // let obj:{a:1}|{b:'3'} = {a: 3}; // 报错 // let obj2:{a:1}|{b:'3'} = {a: '2'}; // 报错 let obj3:{
a:1}|{
b:'3'} = {
b: '3'}; // let obj4:{a:1}|{b:'3'} = {b: 2}; // 报错 // let obj4:{a:1}|{b:'3'} = {b: '5'}; // 报错
6.交叉类型
// 交叉类型 & let a:number&string; // 不会有任何值满足这个类型(又是数字,又是字符串)❌ let obj:{
name: string, age:number} & {
height: number}; obj = {
name: 'xiaotian', age: 19, height: 20} // 属性必须全部要有,少了一个都报错 // 如果一个属性出现多次类型的设置,必须都要满足才行 let obj1:{
name: string, age:number} & {
height: number, age: 18}; // obj1 = {name: 'xiaotian', age: 19, height: 20} // 报错, age不满足18 obj1 = {
name: 'xiaotian', age: 18, height: 20}
7. any和unknown的区别
讯享网// any:不推荐使用any let a:any = 1; // 不会去校验类型,和js没区别了 a = '123' a = [1,2,3] a.toFixed(2) // 绕过类型检测 // unknown:不知道什么类型 let n:unknown; n = 1; n = '123'; // n.toFixed(2) // 报错,有做类型检测,除非把unknown换成number
8. 接口类型interface
export {
} // interface 相当于自定义类型 // 定义接口类型 ==> 给对象用的 interface MyItf {
// 属性名: 值的类型 name: string; // 必须是分号; age: number; height: number; } let obj:MyItf; obj = {
name: 'xiaotian', age: 19, height: 180 } // 定义接口类型 ==> 给对象用的给数组用 interface ArrItf {
// [idx:number] 下标的类型: 值的类型 [idx:number]: number | string } let arr:ArrItf = [1,2,3,'4','5'] // 定义接口类型 ==> 给函数用的 interface FnItf {
(p: string): void } let fn:FnItf = (p: string) => {
} fn('')
9. 继承
讯享网interface NameItf {
name: string } interface AgeItf {
age: number } // 接口继承格式,特点:具有父接口的属性类型 interface PersonItf extends NameItf, AgeItf {
height: number } let p:PersonItf; p = {
name: 'xiaotian', age: 19, height: 180 }
10. 同名
接口可以同名,特点:相当于合并了所有属性类型
interface AItf {
a: string; } interface AItf {
b: number; } let obj:AItf = {
// 只写一个属性会报错 a: 'hhh', b: 1 }
11. 缺省
讯享网interface ObjItf {
name: string; age?: number; // 冒号前面加上问号,表示该属性可以省略不写 } let obj:ObjItf = {
name: 'xiaotian' }
12. 只读
interface ObjItf {
readonly name: string; // 只读 readonly age: number; } let obj:ObjItf = {
name: 'xiaotian', age: 19 } obj.name = 'hhh' // 报错,a属性只可读
13. 联合交叉类型
讯享网// & 优先于 | let obj: {
name: string} | {
age: number} & {
name: number} | {
age: string} obj = {
name: 'xiaotian', age: 19 // 或 // name: 123, // age: '19' }
14. 类型别名
// 自定义类型 type StringOrNumber = string | number let str:StringOrNumber = 1; str = "123"; type ObjType = {
a:number&2, b: string} // type ObjType = {c:string} // 报错,不能重复定义 let obj:ObjType = {
a: 2, // 数字类型,并且要为2 b: 'xiaotian' }
interface和type的区别:
讯享网interface(接口类型) 和 type(类型别名) 的区别: 可以用来自定义类型,类型别名(type)不支持重复定义,接口类型可以
interface和type结合使用:
// interface可以和type结合使用 interface AItf {
a: string } // 用类型别名保存接口上的某个属性类型 type Atype = AItf['a'] // Atype拿到的是一个string let str2:Atype = '10'
15. ts函数
讯享网// 1、原始类型 function fn(a:number, b:number):number {
return a + b } // 2、接口定义函数类型 interface FnItf {
(p: string): number } let fn1:FnItf = (p: string) => {
return 1 } fn1('123') // 3、类型别名定义函数类型 type FnType = (p:string) => void let fn2:FnType = (p: string) => {
} fn2('123') // 4、函数作为对象的属性(接口类型) // 写法1: interface FnItf {
(p: string): number } interface ObjItf {
fn: FnItf } // 写法2: interface ObjItf {
fn: (p: string) => number } let obj:ObjItf = {
fn: (str) => {
return 1 } } obj.fn('123') // 5、类型别名定义函数类型(类型别名) type ObjType = {
fn: (p:string) => number} let obj:ObjType = {
fn: (str) => {
return 1 } } obj.fn('123')
16. ts函数参数的写法
function fn(a:number, b:number) {
return a + b } fn(1, 2) // fn(1) // 报错,因为第二个参数未给 // 默认参数 function fn(a:number, b:number = 2) {
return a + b } fn(1, 2) fn(1) // 缺省参数 function fn1(a:number, b?:number) {
return 1 } fn1(1, 2) fn1(1) // 剩余参数 function fn2(a:number, b:number, ...arr:number[]) {
return 1 } fn2(1, 2, 3, 4, 5)
17. ts中的Promise
写法1:
讯享网interface ResItf {
code: number; data: {
a: number, b: number }[]; // 写法1 message: string; } let p:Promise<ResItf> = new Promise((resolve, reject) => {
resolve({
code: 0, data: [{
a: 1, b: 2 }, {
a: 11, b: 22 }], message: '' }) }) p.then(res => {
if (res.code === 0) {
res.data.map(item => item.a) } })
写法2:
interface DataItf {
a: number; b: number; } interface ResItf {
code: number; data: DataItf[]; // 写法2 message: string; } // Promise对象写法: 对象名:Promise<res的类型> // ResItf的类型 let p:Promise<ResItf> = new Promise((resolve, reject) => {
resolve({
code: 0, data: [{
a: 1, b: 2 }, {
a: 11, b: 22 }], message: '' }) }) p.then(res => {
if (res.code === 0) {
res.data.map(item => item.a) } })
18. this的指向问题
18.1 未加export{}
讯享网// 在全局上,给Window接口扩展这个属性 interface Window {
myname: string } // ts提供Window类型,window就是Window类型的对象 function Person(this:Window, name:string) {
// 在ts的书写中,需要指明this的指向,在函数第一个形参的位置注明 // Window类型中没有myname这个属性,需要自己扩展该属性(利用接口可以同名) this.myname = name } window.Person('')
18.2 加了export{}
// 在普通ts文件中 export {
} // 加了export{}, 这里就不是全局,在该文件中扩展的Window接口就失效了,需要写到 global.d.ts 中 function Person(this:Window, name:string) {
this.myname = name } // 这里不是全局的,Person不是window下的属性,我们需要赋值到window.Person上 window.Person = Person window.Person('') // 在 global.d.ts 文件中 // 在全局上给Window接口扩展这个属性 interface Window {
Person: (n:string) => void; myname: string; }
19. 让this指向自定义对象
讯享网export {
} type ObjType = {
myname:string; Person: (n:string) => void; } let obj:ObjType = {
myname: 'xiaotian', Person: () => {
} } // 定义函数的时候,this的类型,必须要和调用的时候的类型一致 function Person(this: ObjType, name:string) {
this.myname = name } obj.Person = Person obj.Person('hhh')
20. this指向的联合类型的写法(18和19的联合使用)
// this: Window|ObjType function Person(this: Window|ObjType, name:string) {
this.myname = name } obj.Person = Person obj.Person('hhh') // 必须要在 global.d.ts 中扩展了该属性 window.Person = Person window.Person('')
21. 枚举
讯享网// 枚举不是类型,不是用来定义数据类型的,用来列举数据用的 // 写法: enum Xxx {
a = 1, // 逗号 b = '123', } enum StatusCode {
success = 200, error = 404 } let code:string|number = 200; if (code === StatusCode.success) {
console.log('成功'); } else if (code === StatusCode.error) {
console.log('服务器错误'); }
22. 泛型
1. 泛型的基本写法
// 泛型:指的是类型参数化,即将原来某种具体的类型参数化 // 如果参数不确定,string|number用 | 会让代码变得不利于观看 function fn(n:string|number):string|number {
return n } fn('123') fn(1) // 基本写法 // 泛型可以理解为类型的形参,T是一个自定义标识符,表示某种类型 // 单个类型参数 function fn1<T>(n:T):T {
return n } fn1<number>(123) fn1<boolean>(true) fn1<'hello'>('hello') // 多个类型参数 function fn2<T, Y>(n:T, m: Y):T {
return n } fn2<number, boolean>(123, true)
2. 泛型 => 类型别名写法
讯享网// 泛型 => 类型别名 type ObjType<N, G> = {
name:N; getName:() => G } let obj:ObjType<string, number> = {
name: 'xiaotian', getName() {
return 1 } }
3. 泛型 => 接口类型写法
// 泛型 => 接口类型 interface ObjItf<N, G> {
name: N; getName: () => G } let obj2:ObjItf<string, number> = {
name: 'xiaotian', getName() {
return 1 } }
4. 泛型约束
讯享网interface ObjItf<N extends number|string, G=number> {
name: N; // 要求:name只能为数字或字符串 getName: () => G } let obj3:ObjItf<string, number> = {
name: 'xiaotian', getName() {
return 1 } }
23. 类
1. 类的基本写法
// 定义类的同时,会生成一个同名的接口 class Person {
// 定义属性前,应该先声明这个属性的类型,也可以设置默认值 // 这里的myName决定的是下面 this.myName 接收的参数类型 myName:string = "默认名称"; constructor(name:string) {
this.myName = name } getName() {
return this.myName } } let p = new Person('xiaotian') // 上面的这个类,相当于下面这个接口 interface Person {
myName:string; getName: () => string } let obj:Person = {
myName: '', getName() {
return '' } }
2. 类的继承
讯享网class Person {
myName:string constructor(name:string) {
this.myName = name } } class Man extends Person {
age:number constructor(name:string, age:number) {
// super相当于调用父类的构造函数(执行父的constructor) super(name) this.age = age } } let m = new Man('xiaotian', 19)
3. 类的修饰符
public、protected、private
// 在类里定义的属性,默认的修饰符就是public,public修饰的属性或方法可以在类的内部、外部以及子类访问 // protected 受保护的,类的里面,子类可以访问,外部不能访问 // private 私有的,只能在该类里才能访问,子类和类外面不能访问 // readonly 只读 class Person {
// 在属性或方法前写修饰符 public readonly myName:string constructor(name:string) {
this.myName = name } public getName() {
return this.myName } } class Man extends Person {
age:number constructor(name:string, age:number) {
super(name) this.age = age } } let m = new Man('xiaotian', 19) console.log(m.myName); console.log(m.getName()); console.log(m.age);
4. 类的静态属性
讯享网class Person {
public readonly myName:string static title:string = '这是title的值' // 静态属性 constructor(name:string) {
this.myName = name } public getName() {
return this.myName } } // 只能通过类去访问/修改 console.log(Person.title); Person.title = '这是修改后title的值' console.log(Person.title); let p = new Person('xiaotian') // console.log(p.title); // 报错,静态属性不能通过实例对象访问
5. 抽象类
// abstract 抽象类:是普通类的描述,制定一个类的规范,给普通类去继承 // 继承之后,普通类里面就必须定义抽象类里面的抽象属性和抽象方法。抽象类里面的普通方法可以直接继承,在普通类里面不用实现 abstract class Person {
// 抽象属性 abstract name:string // 抽象方法 abstract getName(): number // 也可以写普通方法的 ... getAge() {
return 19 } } // 普通类 class Man extends Person {
name:string = '默认值' getName() {
return 1 } } let m = new Man() // let p = new Person() // 报错,抽象类不能被实例化
6. 书写接口给类使用
讯享网interface PerItf {
name:string; age?:number; // 可以缺省 getName: () => void } // implements class M implements PerItf {
name:string = 'xiaotian'; age:number = 19; getName() {
} } let man = new M()
抽象类给类写的接口都是用来给类制定规范的
24. 工具类型
1. Partial
interface PerItf {
name:string; age:number; } // Partial作用:把<>里面这个接口类型设置为可缺省的属性,类似于 age?:number|undefined(也可以是undefined) let obj:Partial<PerItf> = {
name: 'xiaotian' }
2. Required
讯享网interface Per2Itf {
name:string; age:number; height?:number; } // Required作用:将可缺省的全部变为不可缺省 let obj2:Required<Per2Itf> = {
name: 'xiaotian', age: 19, height: 180 // 不写会报错 }
25. keyof 、in 和 typeof
1. keyof
interface Person {
name:string; age:number; [idx:number]:string|number; // 只看前部分 [idx:number],这样类型就可以是number了 } // keyof后面一般跟接口,表示接口这些属性名之一(key值),实际上就是接口冒号前的部分,冒号后的类型无所谓 type PType = keyof Person // "name" | "age" 这两个常量 let p1:PType; p1 = 'name' p1 = 'age' // 加了[idx:number]后: p1 = 123
2. in
讯享网// in type StrOrNum = string|number; type PTypeIn = {
[k in StrOrNum]: string } let obj:PTypeIn = {
a: '', 10: '' }
3. typeof
// typeof: 用来提取变量或对象的类型 // 变量类型提取 let str = '123'; type StrType = typeof str; // 提取到str的类型为string let a:StrType = 'hhh' // let b:StrType = 1 // 报错,只能是字符串 // 对象类型提取 let obj1 = {
name: '', age: 19, height: 0 } type ObjType = typeof obj1; let obj2:ObjType = {
name: 'xiaotian', age: 19, height: 180 }

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/39810.html