: number;
[propName: string]: any;
解决办法二:
将这个对象赋值给一个另一个变量: 因为 squareOptions不会经过额外属性检查,所以编译器不会报错。
let squareOptions = { colour: "red", width: 100 };
let mySquare = createSquare(squareOptions);
(4)用接口描述函数类型:(输入输出判断)
为了使用接口表示函数类型,我们需要给接口定义一个调用签名。 它就像是一个只有参数列表和返回值类型的函数定义。参数列表里的每个参数都需要名字和类型。对于函数类型的类型检查来说,函数的参数名不需要与接口里定义的名字相匹配。
interface SearchFunc {
(source: string, subString: string): boolean;
let mySearch: SearchFunc;
mySearch = function(src: string, sub: string): boolean {
let result = src.search(sub);
return result > -1;
// 函数的参数会逐个进行检查,要求对应位置上的参数类型是兼容的。 如果你不想指定类型,TypeScript的类型系统会推断出参数类型,因为函数直接赋值给了 SearchFunc类型变量。 函数的返回值类型是通过其返回值推断出来的(此例是 false和true)。 如果让这个函数返回数字或字符串,类型检查器会警告我们函数的返回值类型与 SearchFunc接口中的定义不匹配。
(5)可索引的类型:
可索引类型具有一个 索引签名,它描述了对象索引的类型,还有相应的索引返回值类型。
interface StringArray {
[index: number]: string;
} // 索引签名
let myArray: StringArray;
myArray = ["Bob", "Fred"];
let myStr: string = myArray[0];
// 我们定义了StringArray接口,它具有索引签名。 这个索引签名表示了当用 number去索引StringArray时会得到string类型的返回值。
TypeScript支持两种索引签名:字符串和数字。 可以同时使用两种类型的索引,但是数字索引的返回值必须是字符串索引返回值类型的子类型。 这是因为当使用 number来索引时,JavaScript会将它转换成string然后再去索引对象。 也就是说用 100(一个number)去索引等同于使用"100"(一个string)去索引,因此两者需要保持一致。
字符串索引签名能够很好的描述dictionary模式,并且它们也会确保所有属性与其返回值类型相匹配。 因为字符串索引声明了 obj.property和obj["property"]两种形式都可以
interface NumberDictionary {
[index: string]: number;
length: number; // 可以,length是number类型。数字索引的返回值必须是字符串索引返回值类型的子类型
name: string // 错误,`name`的类型与索引类型返回值的类型不匹配,应该是number 类型
最后,你可以将索引签名设置为只读,这样就防止了给索引赋值:
interface ReadonlyStringArray {
readonly [index: number]: string;
let myArray: ReadonlyStringArray = ["Alice", "Bob"];
myArray[2] = "Mallory"; // error!
// 你不能设置myArray[2],因为索引签名是只读的。
(6)类类型,继承接口:将在《类与接口》部分补充
(1)用接口表示数组:
NumberArray表示:只要索引的类型是数字时,那么值的类型必须是数字。
虽然接口也可以用来描述数组,但是我们一般不会这么做,因为这种方式比前两种方式复杂多了。类数组除外
interface NumberArray {
[index: number]: number;
let fibonacci: NumberArray = [1, 1, 2, 3, 5];
(2)类数组:
类数组不是数组类型!
下例除了约束当索引的类型是数字时,值的类型必须是数字之外,也约束了它还有 length和 callee两个属性
function sum() {
let args: {
[index: number]: number;
length: number;
callee: Function;
} = arguments;
内置对象有IArguments, NodeList, HTMLCollection是TS定义好的类型,有自己的接口定义:
function sum() {
let args: IArguments = arguments;
interface IArguments {
[index: number]: any;
length: number;
callee: Function;
// Type 'IArguments' is missing the following properties from type 'number[]': pop, push, concat, join, and 24 more.
(3)any在数组中的应用:
数组中允许出现任意类型:
let list: any[] = ['xcatliu', 25, { website: 'http://xcatliu.com' }];
函数表达式的约束:
let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
return x + y;
// 对等号右侧的匿名函数进行了类型定义,而等号左边的 mySum,是通过赋值操作进行类型推论而推断出来的。手动给等号左边添加类型应该这样
注意:不要混淆了 TypeScript 中的 =>和 ES6 中的 =>。
在 TypeScript 的类型定义中,=>用来表示函数的定义,左边是输入类型,需要用括号括起来,右边是输出类型。
在 ES6 中,=>叫做箭头函数,应用十分广泛,
(3)用接口定义函数的形状,见《接口》部分第三part
(4)函数中的可选参数,见《接口》第一part《可选参数》
需要注意的是,可选参数必须接在必需参数后面。换句话说,可选参数后面不允许再出现必需参数了
(5)参数默认值:
在 ES6 中,我们允许给函数的参数添加默认值,TypeScript 会将添加了默认值的参数识别为可选参数,此时就不受「可选参数必须接在必需参数后面」的限制了:
function buildName(firstName: string = 'Tom', lastName: string) {
return firstName + ' ' + lastName;
let tomcat = buildName('Tom', 'Cat');
let cat = buildName(undefined, 'Cat');
(6)剩余参数的获取:
使用 ...rest的方式获取函数中的剩余参数(rest 参数):
function push(array: any[], ...items: any[]) {
items.forEach(function(item) {
array.push(item);
let a = [];
push(a, 1, 2, 3);
(7)重载:
重载允许一个函数接受不同数量或类型的参数时,作出不同的处理。
比如,我们需要实现一个函数 reverse,输入数字 123的时候,输出反转的数字 321,输入字符串 'hello'的时候,输出反转的字符串 'olleh'。
这时,我们可以使用重载定义多个 reverse的函数类型:
function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
if (typeof x === 'number') {
return Number(x.toString().split('').reverse().join(''));
} else if (typeof x === 'string') {
return x.split('').reverse().join('');
我们重复定义了多次函数 reverse,前几次都是函数定义,最后一次是函数实现。在编辑器的代码提示中,可以正确的看到前两个提示。
注意,TypeScript 会优先从最前面的函数定义开始匹配,所以多个函数定义如果有包含关系,需要优先把精确的定义写在前面。