TypeScript接口、type关键字详解(可读、只读属性、继承接口 | 您所在的位置:网站首页 › 接口继承的别名 › TypeScript接口、type关键字详解(可读、只读属性、继承接口 |
目录 TypeScript接口 可选属性 :? 只读属性 ReadonlyArray 接口继承接口(extends) 接口继承类(extends) 接口规范类(implements) 函数类型接口 可索引类型接口 只读设置 类类型接口 规定构造函数 混合类型接口 type关键字 type扩展(&) interface继承type 映射类型 type高级使用 TypeScript接口用于规范定义变量的类型,规定变量应该具有什么属性或函数入参什么值返回什么值等。 interface IUser { name: string age: number } let user: IUser = { name : 'yf', age: 32 } 可选属性带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个?符号。定义的属性可以不用实现。 interface IUser { name: string age?: number } let user: IUser = { name : 'yf' } :?注意区分冒号后也可以接问号。 const gender: ?number = undefined; // 等同于下面这种写法 const gender: number | null | void = undefined 只读属性只读属性只能在对象刚刚创建的时候修改其值。 在属性名前用readonly来指定只读属性 。 interface Point { readonly x: number; readonly y: number; } let p1: Point = { x: 10, y: 20 }; p1.x = 5; // error! ReadonlyArray表示数组创建后再也不能被修改 let a: number[] = [1, 2, 3, 4]; let ro: ReadonlyArray = a; ro[0] = 12; // error! ro.push(5); // error! ro.length = 100; // error! a = ro; // error!注意最后a=ro,将ReadonlyArray赋值到一个普通数组也是不可以的。 但是你可以用类型断言重写 a = ro as number[]; 接口继承接口(extends)一个接口可以继承多个接口,创建出多个接口的合成接口,继承的每个接口里的内容都需要满足。 interface Shape { color: string; } interface PenStroke { penWidth: number; } interface Square extends Shape, PenStroke { sideLength: number; } let square:Square = { color: 'bule', sideLength: 0, penWidth: 0 }; 接口继承类(extends)当接口继承了一个类类型时,它会继承类的成员但不包括其实现。 就好像接口声明了所有类中存在的成员,但并没有提供具体实现一样。 例如下面接口继承了Control类,故接口约束的abc类中需要定义pubulic的state属性 class Control { state: any; } interface SelectableControl extends Control { select(): void; } class abc implements SelectableControl { state: any select() { } }注意接口也能继承到类的private和protected成员。但继承后这个接口类型只能被这个类或其子类所实现。 例如下面abc实现SelectableControl接口就必须是Control类的子类,因为state属性是私有属性。 class Control { private state: any; } interface SelectableControl extends Control { select(): void; } class abc extends Control implements SelectableControl { select() { } } 接口规范类(implements)相当于用接口规范便量时的冒号:,同样也可以通过逗号用多个接口约束一个类。 注意接口中定义的属性,必须在初始时定义,如果仅在constructor中定义也会报错,例如下面h不能仅在constructor中定义 interface ClockInterface { tick(); } interface Clock { h: number } class DigitalClock implements ClockInterface,Clock { //h: string //放开此行注释为正确的 constructor(h: number, m: number) { } //error缺少h属性 tick() { console.log("beep beep"); } } 函数类型接口括号里为参数,冒号右边为函数的返回值。 函数的参数会逐个进行检查,只要求对应位置上的参数类型是兼容的。所以函数的参数名不需要与接口里定义的名字相同。 interface SearchFunc { (source: string, subString: string): boolean; } let mySearch: SearchFunc = function(so: string, su: string) { let result = so.search(su); return result > -1; } 可索引类型接口可索引类型具有一个索引签名,它描述了对象索引的类型,还有相应的索引返回值类型。 它共有支持两种索引签名:字符串和数字。 注意同时使用两种类型的索引时,数字索引的返回值必须是字符串索引返回值类型的子类型。 这是因为当使用number来索引时,JavaScript会将它转换成string然后再去索引对象。 也就是说用100(一个number)去索引等同于使用"100"(一个string)去索引,因此两者需要保持一致。 class Animal { name: string; } class Dog extends Animal { breed: string; } interface NotOkay { [x: number]: Animal; [x: string]: Dog; }// 错误:使用'string'索引,有时会得到Animal,数字索引应该是字符串索引的子集 interface NotOkay { [x: number]: Dog; [x: string]: Animal; }//OK注意使用了可索引类型后,另外定义的属性需要符合可索引。例如下面额外定义了字符串name属性,而使用的可索引也是字符串,所以指向的值应该相同。 interface NumberDictionary { [index: string]: number; length: number; // 可以,length是number类型 name: string // 错误,`name`的类型与索引类型返回值的类型不匹配 } 只读设置可以将索引签名设置为只读,这样就防止了给索引赋值 interface ReadonlyStringArray { readonly [index: number]: string; } let myArray: ReadonlyStringArray = ["Alice", "Bob"]; myArray[2] = "Mallory"; // error! 类类型接口接口描述了类的公共部分,而不是公共和私有两部分。 它不会检查类是否具有某些私有成员。 interface ClockInterface { currentTime: Date; } class Clock implements ClockInterface { private currentTime: Date;//error ,只能为public constructor(h: number, m: number) { } } 规定构造函数注意类是具有两个类型的:静态部分的类型和实例的类型 , constructor存在于类的静态部分,所以不在检查的范围内。 故下面通过在接口里new定义构造函数会报错 interface ClockConstructor { new (hour: number, minute: number); } class Clock implements ClockConstructor { //error,接口中的new无法直接在类里面实现 currentTime: Date; constructor(h: number, m: number) { } }但是我们可以借助函数的的形式去实现,例如下面 interface ClockInterface { tick(); } class DigitalClock implements ClockInterface { constructor(h: number, m: number) { } tick() { console.log("beep beep"); } } class AnalogClock implements ClockInterface { constructor(h: number, m: number) { } tick() { console.log("tick tock"); } } interface ClockConstructor { new (hour: number, minute: number): ClockInterface; } function createClock(ctor: ClockConstructor, hour: number, minute: number){ return new ctor(hour, minute); } let digital = createClock(DigitalClock, 12, 17); let analog = createClock(AnalogClock, 7, 32); 混合类型接口一个对象可以同时做为函数和对象使用,并带有额外的属性。 需要借助类型断言,例如下面: interface Counter { (start: number): string; interval: number; reset(): void; } function getCounter(): Counter { let counter = function (start: number) { }; counter.interval = 123; counter.reset = function () { }; return counter; } let c = getCounter(); c(10); c.reset(); c.interval = 5.0; type关键字用于给类型起一个新名字,支持基本类型、联合类型、元祖及其它任何你需要的手写类型,常用于联合类型。 type test = number; //基本类型 let num: test = 10; type userOjb = {name:string} // 对象 type getName = ()=>string // 函数 type data = [number,string] // 元组 type numOrFun = Second | getName // 联合类型 type扩展(&)interface的扩展可以通过type交叉(&)类型实现。 type Name = { name: string; } type User = Name & {age: number} let stu:User={name: 'wang', age: 18}interface交叉(&)可以实现type类型。 interface Name { name: string; } type User = Name & { age: number; } let stu:User={name:'wang', age: 18} interface继承type接口可以继承type类型。 type Name = { name: string; } interface User extends Name { age: number; } let stu:User={name: 'wang', age: 89} 映射类型type可以使用关键字生成映射类型。 type Keys = "name" | "sex" type DuKey = { [Key in Keys]: string //类似 for ... in } let stu: Dukey = { name: 'wang', sex: 'man' } type高级使用编写TypeScript工具类型,你需要知道的知识_胖子依然6的博客-CSDN博客_typescript 工具类型 补充: // 将所有属性变成可选的 type Optional = { [key in keyof T]?: T[key]; } // 将某些属性变成必选的 type MyRequired = T & { [key in K]-?: T[key]; }; // 例如我们有个实体 type App = { _id?: string; appId: string; name: string; description: string; ownerList: string[]; createdAt?: number; updatedAt?: number; }; // 我们在更新这个对象/类型的时候,有些 key 是必填的,有些 key 是选填的,这个时候就可以这样子生成我们需要的类型 type AppUpdatePayload = MyRequired |
CopyRight 2018-2019 实验室设备网 版权所有 |