【TypeScript】Re01
参考视频:
1 | https: //www.bilibili.com/video/BV14Z4y1u7pi |
JS已有类型:
1 2 | 基础类型 number / string / boolean / null / undefined / symbol 对象类型 object (数组,对象, 函数) |
TS类型:
1 2 3 4 5 6 7 8 | 1、联合类型 2、类型别名 3、接口 4、元组 5、字面量类型 6、枚举 7、void 8、any |
函数类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | function add1(n1: number, n2: number): number { return num1 + num2 } // 箭头函数可以在注解方法参数时指定参数类型和返回类型 const add2 = (n1: number, n2: number): number => n1 + n2 // 或者第二种,直接对变量注解方法类型 const add3: (n1: number, n2: number) => number = (n1, n2) => n1 + n2 // 函数无返回类型时注解为 void function greet(name: string): void { console.log( 'hello' , name) } // 或者这样写 const greet: (name: string) => void = name => console.log( 'hello' , name) // 可选参数, 一般放在必填参数的后面使用 function mySlice(start?: number, end?: number): void { console.log( '起始索引' , start, '结束索引' , end) } |
对象类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | let person: { name: string, age: number, sayHi(): void, greet(name: string): void } = { name: 'jack' , age: 19, sayHi(){}, greet(){} } // 如果是注解成一行编写 let person: { name: string; age: number; sayHi(): void; greet(name: string): void; } // 可选属性 function myAxios(config: { url: string; method?: string }) {} myAxios(url: 'asdasdasd' ) |
接口类型:
1 2 3 4 5 6 7 8 9 10 11 12 | // 用于复用对象类型 interface IPerson = { name: string age: number sayHi(): void } let person: IPerson = { name: 'jack' , age: 19, sayHi() {} } |
接口和类型别名的区别:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 接口只能为对象指定类型 类型别名:包括对象类型,支持任意类型 interface IPerson = { name: string age: number sayHi(): void } type IPerson = { name: string age: number sayHi(): void } type NumStr = number | string |
接口继承:
1 2 3 4 5 6 7 | // 接口继承,用于多余属性复用 interface Point2D { x: number; y: number } interface Point3D { x: number; y: number; z: number } // x轴和y轴都冗余了,使用extends实现 interface Point2D { x: number; y: number } interface Point3D extends Point2D { z: number } |
元组类型:
1 2 3 4 5 6 7 | 经纬度,长度固定2个 // 数组长度可以多个 let position: number[] = [39.5427, 116.1327] // 元组固定两个元素 let point: [number, number] = [39.5427, 116.1327] |
类型断言:
1 2 3 4 5 | // 强制断言一个类型 const aLink = document.getElementById( 'link' ) as HTMLAnchorElement // 语法2 const aLink = <HTMLAnchorElement>document.getElementById( 'link' ) |
字面量类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // let是变量 值可以是任意字符, ts推测类型是string let str1 = 'Hello TS' // const是常量 值不能变化只能是hello ts 所以类型即为 hello ts const str2 = 'Hello TS' // 显示声明 let str1: string = 'Hello TS' const str2: 'Hello TS' = 'Hello TS' // 当变量定义常量值类型时,等效const let age: 18 = 18 // 结合 联合类型处理,只能在已列出的几种常量中选择 function directionChangeTo(direction: 'up' | 'down' | 'left' | 'right' ) { console.log(direction) } |
枚举类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 代替联合类型,更具体的表示入参选项 enum Direction { Up, Down, Left, Right } // 方法参数声明 function changeDirection(direction: Direction): void { console.log(direction) } // 箭头函数声明 const changeDirection2: (direction: Direction) => void = direction => { console.log(direction) } // 调用 changeDirection(Direction.Up) // 枚举是存在默认值的(自增下标),支持自定义值 enum Direction { Up = 2, Down = 4, Left = 8, Right = 16 } // 如果是字符串枚举,则没有自增迭代值了 enum Direction { Up = 'Up' , Down = 'Down' , Left = 'Left' , Right = 'Right' } |
any类型:
1 2 3 4 5 | // 失去TS类型保护, 不再编译警告 let obj: any = { x: 0 } obj.bar = 100 obj() const n: number = obj |
typeof 操作符
1 2 3 4 5 6 7 8 9 10 11 12 | 1、在类型上下文中引用变量或者属性的类型 根据已有变量获得该变量的类型描述 2、只能用来查询变量或属性的类型,无法查询其它形式的类型 // 不使用typeof let p = { x: 1, y: 2} function formatPoint(point: { x: number; y: number }) {} formatPoint(p) // 使用typeof function formatPoint(point: typeof p) {} |
高级类型
1 2 3 4 5 6 | - Class类 - 类型兼容性 - 交叉类型 - 泛型 + Keyof - 索引签名 + 索引查询 - 映射类型 |
Class类-1 创建类和属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // js 语法 class Person {} const p = new Person() // ts 创建类和属性 class Person { age: number gender = '男' // 构造器默认为类的类型 constructor(age: number, gender: string) { this .age = age this .gender = gender } } const p = new Person(18, '男' ) |
Class类-2 实例方法
1 2 3 4 5 6 7 8 9 10 11 12 | // 实例方法 class Point { x = 1 y = 2 scale(n: number) { this .x *= n this .y *= n } } const p = new Point() p.scale(10) |
Class类-3 类的继承
1 2 3 4 5 6 7 8 9 10 11 12 13 | // class的继承 class Animal { move() { console.log( 'Moving along' ) } } class Dog extends Animal { name = '二哈' bark() { console.log( '汪' ) } } const dog = new Dog() dog.move() dog.bark() console.log( '旺旺' ) |
Class类-4 接口的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | // class 的实现 interface Singable { sing(): void name: string } class Person implements Singable { name = 'jack' sing() { console.log( '13766~' ) } } const jack = new Person() jack.name jack.sing() |
Class类-5 访问修饰符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | // 访问修饰符 public -> protected -> private // 默认可见性 public,即省略不写 class Animal { public move() { console.log( '' ) } } // protected 仅对所在类和子类中可见(实例对象不可见) class Animal { protected move() { console.log( 'Moving along' ) } } class Dog extends Animal { bark() { console.log( '汪' ) this .move() } } // private 只在当前类中可见(实例对象及子类不可见) // 编写规范, private 方法名称 使用双下划线修饰左右两边 class Animal { private __move__() { console.log( 'Moving along' ) } walk() { this .__move__() } } // readonly 只读修饰符,只读防止在构造函数之外对函数赋值,只能修饰属性,不能修饰方法 // 接口或者{}表示的对象类型也支持readonly修饰 class Person { readonly age: number = 18 // 提供一个默认值 constructor(age: number) { this .age = age } } |
类型兼容问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | // 类型兼容问题 类型系统:Structural Type System (结构化类型系统), Nominal Type System (标明类型系统) TS用STS系统 Duck Typing 类型检查关注值本身的类型,如果对象具有相同形状,则类型相同 // Duck Typing 如果它走路像鸭子,声音像鸭子,样子也像鸭子,那他就是鸭子 // NTS标明类型系统 例如Java 即使字段属性一样,但是不是同类型,就不兼容(以接口方式进行兼容) // 样例 class Point { x: number; y: number } class Point2D { x: number; y: number } const p: Point = new Point2D() // Class以多兼容少 class Point { x: number; y: number } class Point3D { x: number; y: number; z: number } const p: Point = new Point3D() // interface以多兼容少,同属性兼容 interface Point { x: number; y: number } interface Point2D { x: number; y: number } let p1: Point let p2: Point2D = p1 interface Point3D { x: number; y: number; z: number } let p3: Point3D p2 = p3 // 如果class 和 interface 同属性,方法,一样兼容的 |
函数类型兼容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | // 函数兼容 // 参数个数,参数类型,返回值类型 // 1、参数个数兼容, 参数多的函数兼容参数少的函数 type Fun1 = (a: number) => void type Fun2 = (a: number, b: number) => void let fun1 = Fun1 let fun2 = Fun2 = fun1 // 2、方法样例, forEach自动推导函数参数个数和类型 const arr = [1, 2, 3] arr.forEach(() => {}) arr.forEach(item => {}) 3、参数类型兼容 interface Point { x: number; y: number } interface Point3D { x: number; y: number; z: number } type F2 = (p: Point2D) => void type F3 = (p: Point3D) => void let f2: F2 f3 = f2 4、返回值类型同理 type F7 = () => { name: string } type F8 = () => { name: string; age: number } let f7: F7 let f8: F8 f7 = f8 |
接口交叉类型:
类型组合在一起实现
1 2 3 4 5 6 7 8 | // 交叉类型 交叉符& 联合两个接口的属性,成一个新的类型 interface Person { name: string } interface Contact { phone: string } type PersonContact = Person & Contact let pc: PersonContact = { name: 'cloud9' , phone: '13755684304' } |
交叉类型和继承的区别?
1 2 3 4 5 6 7 8 9 10 11 12 13 | // 交叉类型 和 继承 的区别? 1、都是为了对象类型的组合 2、处理对象类型冲突的属性方式不一样 - extends 会触发冲突警告 - & 会将冲突类型进行联合 interface A { fn: (val: number) => string } interface B extends A { fn: (val: string) => string } // 语法警告 fn类型冲突 interface A { fn: (val: number) => string } interface B { fn: (val: string) => string } type C = A & B // fn: (val: string | number) => string 参数类型将被联合起来 |
TS泛型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | TS 泛型处理: function genericType<Type>(val: Type): Type { return val } const num = genericType<number>(10) const str = genericType<string>( '2334' ) const bool = genericType<boolean>( true ) 泛型约束: // 1、可以约束泛型为具体类型数组 Array<Type> ? function genericTypeConstraint<Type>(val: Type[]): Type[] { return val } // 2、可以指定为某一个类型的子类型 interface ILength { length: number } // 该泛型必须要拥有ILength具备的属性 function genericTypeConstraint<Type extends ILength>(val: Type): Type { console.log(val.length) return val } genericTypeConstraint([1, 2, 3]) genericTypeConstraint( '123' ) genericTypeConstraint({ length: 10, name: 'cloud9' }) // 3、支持添加多个泛型,泛型之间可以进行约束设置 function getProp<Type, Field extends keyof Type>(obj: Type, key: Field) { return obj[key] } let person = { name: 'jack' , age: 18 } getProp(person, 'name' ) getProp(18, 'toFixed' ) getProp( 'abc' , 'split' ) getProp([1, 2, 3], 'length' ) getProp([1, 2, 3], 1) // 4、接口与泛型的组合 interface IdFunc<Type> { id: (val: Type) => Type ids: () => Type[] } // 使用泛型时,需要指定泛型的具体类型 let obj: IdFunc<number> = { id(val) { return val }, ids() { return [1, 3, 5] } } // 5、泛型工具类 Partial<Type> 创建一个Partial类型,该类型泛型的类型属性可选 Readonly<Type> 创建一个ReadOnly类型,该类型泛型的类型属性只读 Pick<Type, Keys> 创建一个Pick类型, 根据Keys类型返回一个新的对象 Record<Keys, Type> 创建一个Record类型,根据Keys和Type返回对象 |
索引类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | // 索引类型签名: interface AnyObject { // key表示键名占位符,可以命名其他名称 // 约束键类型为string, 值类型为number [key: string]: number } let obj: AnyObject = { a: 1, b: 2 } interface MyArray<T> { [idx: number]: T } let arr: MyArray<number> = [1, 3, 5] arr[0] // 映射类型, 只能再type中使用 type PropKeys = 'x' | 'y' | 'z' type Type1 = { x: number, y: number, z: number } type Type2 = { [Key in PropKeys]: number } // 除了联合类型映射,还支持类型键集合映射 type Type3 = { x: number, y: number, z: number } type Type4 = { [Key in keyof Type3]: number } // 索引查询 type Type5 = { x: number, y: string, z: boolean } type TypeX = Type5[ 'x' ] // number, 被查询的键名必须在该类型中存在,否则报错 // 联合查询 查询指定类型中具体某个索引的类型,或者是索引类型的联合 type Type6 = { x: number, y: string, z: boolean } type TypeXwithY = Type6[ 'x' | 'y' ] // number | string type Type6Union = Type6[keyof Type6] // number | string | boolean |
类型声明文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | TS两种文件类型:[***.ts | ****.d.ts] 两种文件的区别? - ts 文件 1、包含类型信息和执行逻辑 2、可以编译为.js文件,然后执行代码 - d.ts 文件 (d代表declare) 1、只包含类型信息的类型声明文件 2、不会生成js文件,仅提供类型信息 d 类似Java的接口 定义 变量、对象类型、方法声明 用法: - - - - - index.d.ts - - - - - type Props = { x: number y: number } export { Props } // 或者直接 export export type Props = { x: number y: number } - - - - - index.ts - - - - - import { Props } from './index' |
ts.config.js 的配置声明:
1 | https: //www.bilibili.com/video/BV14Z4y1u7pi?p=79 |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析