接口_可选属性
接口里的属性不全都是必需的。 有些是只在某些条件下存在,或者根本不存在。 可选属性在应用 “option bags” 模式时很常用,即给函数传入的参数对象中只有部分属性赋值了
带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个 ? 符号
interface SquareConfig { color?: string; width?: number; } function createSquare(config: SquareConfig) { let newSquare = { color: "white", area: 100 } if (config.color) { newSquare.color = config.color; } if (config.width) { newSquare.area = config.width * config.width; } return newSquare; } let mySquare = createSquare({ color: "black" }); console.log(mySquare)
可选属性的好处之一是可以对可能存在的属性进行预定义,好处之二是可以捕获引用了不存在的属性时的错误。 比如,我们故意将 createSquare 里的 color 属性名拼错,就会得到一个错误提示
interface SquareConfig { color?: string; width?: number; } function createSquare(config:SquareConfig){ let newSquare = { color: "white", area: 100 }; if (config.clor) { // Error: Property 'clor' does not exist on type 'SquareConfig' newSquare.color = config.clor; } if (config.width) { newSquare.area = config.width * config.width; } return newSquare; } let mySquare = createSquare({ color: "black"});
接口_只读属性
一些对象属性只能在对象刚刚创建的时候赋值。 你可以在属性名前用 readonly 来指定只读属性
对象操作
interface Point { readonly x: number; readonly y: number; } let p1: Point = { x: 10, y: 20 }; p1.x = 5; // error!
函数操作
interface Point { readonly x: number; readonly y: number; } function MyPoint(ps:Point){ const pt = { x:100, y:200 } // Cannot assign to 'x' because it is a read-only property. ps.x = pt.x; ps.y = pt.y console.log(ps) } MyPoint({ x:100,y:200 })
readonly vs const
最简单判断该用 readonly 还是 const 的方法是看要把它做为变量使用还是做为一个属性。 做为变量使用的话用 const ,若做为属性则使用 readonly
接口_额外的属性检查
我们知道。接口具有“option bags” 模式,那我们来看下面的例子
interface SquareConfig { color?: string; width?: number; } function createSquare(config: SquareConfig) { console.log(config) } let mySquare = createSquare({width: 100 });
现在多了一个需求,在传入的参数中,可能会传入未知参数 colour 因为有“option bags” 模式,会不会允许我们传入未知参数呢?
interface SquareConfig { color?: string; width?: number; } function createSquare(config: SquareConfig) { } let mySquare = createSquare({ colour: "red",width: 100 });
然而,TypeScript 会认为这段代码可能存在 bug
对象字面量会被特殊对待而且会经过“额外属性检查”,你会得到一个错误
error: Object literal may only specify known properties, but 'colour' does not exist in type 'SquareConfig'. Did you mean to write 'color'?
我们可以通过添加额外属性的方式解决这个问题
interface SquareConfig { color?: string; width?: number; [propName: string]: any; } function createSquare(config: SquareConfig) { console.log(config) } let mySquare = createSquare({ colour: "red", width: 100 });
还有最后一种跳过这些检查的方式,这可能会让你感到惊讶,它就是将这个对象赋值给一个另一个变量: 因为 squareOptions 不会经过额外属性检查,所以编译器不会报错
interface SquareConfig { color?: string; width?: number; } function createSquare(config: SquareConfig) { console.log(config) } const squareObj = { colour: "red", width: 100 } let mySquare = createSquare(squareObj);
要留意,在像上面一样的代码里,你可能不应该去绕开这些检查,这不利于代码可读性与纠错性
接口_ 函数类型
接口能够描述 JavaScript 中对象拥有的各种各样的外形。 除了描述带有属性的普通对象外,接口也可以描述函数类型
interface SearchFunc { (source: string, subString: string) }
这样定义后,我们可以像使用其它接口一样使用这个函数类型的接口
let mySearch: SearchFunc; mySearch = function (source: string, subString: string) { console.log(source,subString) }; mySearch("Hello","World")
对于函数类型的类型检查来说,函数的参数名不需要与接口里定义的名字相匹配
interface SearchFunc { (source: string, subString: string) } let mySearch: SearchFunc; mySearch = function (sou: string, sub: string) { console.log(sou,sub) } mySearch("Hello","World")
接口_类类型
与传统面向对象里接口的基本作用一样,TypeScript 也能够用它来明确的强制一个类去符合某种契约
interface UserInterface { job:string } class Teacher implements UserInterface { public job:string public name:string public age:string constructor(name,age){ this.name = name; this.age = age } }
你也可以在接口中描述一个方法,在类里实现它
interface UserInterface { job:string sayHello(j:string):void } class Teacher implements UserInterface { public job:string public name:string public age:string constructor(name,age){ this.name = name; this.age = age } sayHello(j: string) { this.job = j console.log(j,this.name,this.age) } } const t = new Teacher("张三","20"); t.sayHello("itxiaotong")
接口_继承接口
和类一样,接口也可以相互继承。 这让我们能够从一个接口里复制成员到另一个接口里,可以更灵活地将接口分割到可重用的模块里
interface Info{ name:string age:number } interface Job extends Info{ job:string } function user(userInfo:Job){ console.log(userInfo) } user({ name:"iwen",age:20,job:"itxiaotong" })
一个接口可以继承多个接口,创建出多个接口的合成接口
interface Info{ name:string age:number } interface Num{ num:number } interface Job extends Info,Num{ job:string } function user(userInfo:Job){ console.log(userInfo) } user({ name:"iwen",age:20,job:"itbaizhan",num:1001 })