You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
interfaceSquareConfig{color?: string;width?: number;}functioncreateSquare(config: SquareConfig): {color: string;area: number}{letnewSquare={color: "white",area: 100};if(config.clor){// Property 'clor' does not exist on type 'SquareConfig'. Did you mean 'color'?// Error: Property 'clor' does not exist on type 'SquareConfig'newSquare.color=config.clor;// Property 'clor' does not exist on type 'SquareConfig'. Did you mean 'color'?}if(config.width){newSquare.area=config.width*config.width;}returnnewSquare;}letmySquare=createSquare({color: "black"});
leta: number[]=[1,2,3,4];letro: ReadonlyArray<number>=a;ro[0]=12;// error!// Index signature in type 'readonly number[]' only permits reading.ro.push(5);// error!// Property 'push' does not exist on type 'readonly number[]'.ro.length=100;// error!// Cannot assign to 'length' because it is a read-only property.a=ro;// error!// The type 'readonly number[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
从上面的例子最后一行可以看到把 ro 重新辅助回去也会报错,可以用类型断言解决:
leta: number[]=[1,2,3,4];letro: ReadonlyArray<number>=a;a=roasnumber[];
readonly vs const: 在声明变量的时候使用 const, 在声明属性的时候用 readonly
interfaceSquareConfig{color?: string;width?: number;}functioncreateSquare(config: SquareConfig): {color: string;area: number}{return{color: config.color||"red",area: config.width ? config.width*config.width : 20};}letmySquare=createSquare({colour: "red",width: 100});// Argument of type '{ colour: string; width: number; }' is not assignable to parameter of type 'SquareConfig'.// Object literal may only specify known properties, but 'colour' does not exist in type 'SquareConfig'. Did you mean to write 'color'?
letsquareOptions={colour: "red"};letmySquare=createSquare(squareOptions);// Type '{ colour: string; }' has no properties in common with type 'SquareConfig'.
letmySearch: SearchFunc;mySearch=function(src,sub){letresult=src.search(sub);// Type '(src: string, sub: string) => string' is not assignable to type 'SearchFunc'.// Type 'string' is not assignable to type 'boolean'.return"string";};
动态属性声明
接口允许我们声明动态属性来解决 obj["key"] 和 a[10] 动态赋值的场景,动态属性通过 [key: type]: type 格式声明:
索引的类型只支持 string 和 number 类型。在接口中可以同时支持这两种类型,但是数子索引的值类型必须时字符串索引的值类型的子类型,因为在数字索引在对象中会被先转为字符串,比如 a[10] 会转为 a['10']:
interfaceAnimal{name: string;}interfaceDogextendsAnimal{breed: string;}// Error: indexing with a numeric string might get you a completely separate type of Animal!interfaceNotOkay{[x: number]: Animal;// Numeric index type 'Animal' is not assignable to string index type 'Dog'.[x: string]: Dog;}
如果使用 string 类型的索引,它会检查接口的所有属性值必须为索引返回的类型。否则会报错:
interfaceNumberDictionary{[index: string]: number;length: number;// ok, length is a numbername: string;// error, the type of 'name' is not a subtype of the indexer// Property 'name' of type 'string' is not assignable to string index type 'number'.}
动态索引如果返回一个联合类型的话可以解决上面的报错:
interfaceNumberOrStringDictionary{[index: string]: number|string;length: number;// ok, length is a numbername: string;// ok, name is a string}
最后,如果给动态属性加上只读 readonly 限制可以防止动态分配额外属性:
interfaceReadonlyStringArray{readonly[index: number]: string;}letmyArray: ReadonlyStringArray=["Alice","Bob"];myArray[2]="Mallory";// error!// Index signature in type 'ReadonlyStringArray' only permits reading.
interfaceClockConstructor{new(hour: number,minute: number);}classClockimplementsClockConstructor{// Class 'Clock' incorrectly implements interface 'ClockConstructor'.// Type 'Clock' provides no match for the signature 'new (hour: number, minute: number): any'.currentTime: Date;constructor(h: number,m: number){}}
在
TypeScript
中, 接口interface
用来描述一系列属性或者方法以及它们的类型声明的集合结构,它在内部和外部代码中很好地提供一种结构数据的类型约束。第一个例子
类型检查会判断传递给函数的参数是否是一个包含
label
属性并且类型为string
的对象。值得注意的是,传递的对象参数可以包含其他属性。可以用
interface
改造上面例子:可以看出函数参数必须实现这个接口,另外
Typescript
不会去校验属性的顺序,只要包含接口的属性以及正确类型即可。可选属性
当接口描述的属性可选时,可以用
?:
表示:如果访问了不在接口描述的属性,将会抛出错误。 所以对于可能出现的属性,都应该在接口中描述出来。
只读属性
有一些属性在对象创建后就不能被修改了,这是可以在接口属性名前加上
readonly
让其成为只读属性:可以对象字面量构造
Point
, 创建后,x
和y
就不能被修改了:TypeScript
提供了一个ReadonlyArray<T>
数组类型,不同于Array<T>
的是,它移除了所有数组变异方法,这样就能保证创建数组后就不能进行任何修改:从上面的例子最后一行可以看到把
ro
重新辅助回去也会报错,可以用类型断言解决:readonly vs const: 在声明变量的时候使用
const
, 在声明属性的时候用readonly
额外属性检查
在上面第一个例子中,
Typescript
允许我们传递一个具有额外属性的对象给函数,但是把对象换成对象字面量方式传递的话情况就不一样了:用对象字面量赋值给一个接口类型变量或者作为函数参数会出发
TypeScript
的额外属性检测(Excess Proerty Checks)。如果存在没有接口声明中的属性,就会抛出异常。同样的,我们可以用类型断言解决这个报错:更好的一种解决方案是为接口增加动态参数声明,如下:
我们稍后再详细介绍接口动态属性,目前只要知道我们传递的字面量对象可以包含任意额外的任意类型的属性。另外有一个很奇怪的解决方法就是可以把字面量赋值给一个对象,再把对象作为函数参数,也不会报错:
上面不报错的一个原因是传递的对象和接口声明具有公共的属性
width
,否则也会抛出异常:声明函数
接口也可以用来声明函数类型,在接口内声明函数参数列表及类型和返回类型即可:
像其他接口一样使用函数类型的接口:
函数参数名可以不用和声明时一样,并且可以省略参数的类型声明,它会根据接口声明时的类型进行检查,返回类型根据
return
类型进行检查:返回类型和声明时不一样就会抛出异常:
动态属性声明
接口允许我们声明动态属性来解决
obj["key"]
和a[10]
动态赋值的场景,动态属性通过[key: type]: type
格式声明:索引的类型只支持
string
和number
类型。在接口中可以同时支持这两种类型,但是数子索引的值类型必须时字符串索引的值类型的子类型,因为在数字索引在对象中会被先转为字符串,比如a[10]
会转为a['10']
:如果使用
string
类型的索引,它会检查接口的所有属性值必须为索引返回的类型。否则会报错:动态索引如果返回一个联合类型的话可以解决上面的报错:
最后,如果给动态属性加上只读
readonly
限制可以防止动态分配额外属性:Class Types
接口的实现
和其他静态语言一样,可以定义一个类来实现接口:
对于接口定义的方法,也要有具体的实现方法:
注意的是类实现接口的属性和方法是为
public
的不是private
类的静态和实例在实现接口中的不同
如果我们定义一个类型实现一个具有构造标示(
new
函数声明)的接口时,会报错:这是因为
Typescript
只会校验类的实例是否实现了接口,不会去校验类的静态属性。接口继承
和类一样,接口之间可以通过继承来扩展属性,从而使接口定义更加灵活和可复用:
另外接口还支持多重继承:
混合类型
接口可以同时支持函数类型和对象属性类型的混用,不过这一般很少用到:
The text was updated successfully, but these errors were encountered: