typescript对象、数组、函数类型详解
⽬录
⼀、对象的类型:接⼝
概述:在⾯向对象语⾔中,接⼝(Interfaces)是⼀个很重要的概念,它是对⾏为的抽象,⽽具体如何⾏动需要由类(classes)去实现(implements)
1.接⼝使⽤
这个例⼦中定义了⼀个接⼝ Person,接着定义了⼀个变量 tom,它的类型是 Person。这样,我们就约束了 tom 的形状必须和接⼝Person ⼀致
//正确使⽤
interface Person { name: string; age: number; }
let tom: Person = { name: 'Tom', age: 25 };
// 错误案例⼀:定义的变量的属性⽐接⼝少
typeof arrayinterface Person { name: string; age: number; }
let tom: Person = { name: 'Tom' }; // error : Property 'age' is missing in type '{ name: string; }'
// 错误案例⼆:定义的变量的属性⽐接⼝多
interface Person { name: string; age: number; }
let tom: Person = { name: 'Tom', age: 25, gender: 'male' }; // error: 'gender' does not exist in type 'Person'.
结论:赋值的时候,变量的形状必须和接⼝的形状保持⼀致
2.可选属性:
//可选属性案例⼀:正确使⽤
interface Person { name: string; age?: number; }
let tom: Person = { name: 'Tom' }; // ok
let tony: Person = { name: Tony, age: 25}; // ok
//可选属性案例⼆:错误使⽤
interface Person { name: string; age?: number; }
let tom: Person = { name: 'Tom', age: 25, gender: 'male' }; //error: 'gender' does not exist in type 'Person'
结论:可选属性的含义是该属性可以不存在,但仍然不允许添加未定义的属性
3.任意属性:
//任意属性案例⼀:正确使⽤
//使⽤ [propName: string] 定义了任意属性取 string 类型的值
interface Person { name: string; age?: number; [propName: string]: any; }
let tom: Person = { name: 'Tom', gender: 'male' };
//任意属性使⽤:错误使⽤
interface Person {
name: string;
age?: number; // error:类型'number'的属性'age'不能分配给字符串索引类型'string',类型'number'不能分配给'string'类型[propName: string]: string;
}
let tom: Person = {
name: 'Tom',
age: 25,
gender: 'male'
};
结论:⼀旦在接⼝中定义了任意属性,那么确定其中和它并列的属性和可选属性都必须是它的⼦属性
4.只读属性:
概述:有时候我们希望对象中的⼀些字段只能在创建的时候被赋值,那么可以⽤ readonly 定义只读属性
// 错误案例使⽤⼀:
interface Person {
readonly id: number;
name: string;
age?: number;
[propName: string]: any;
}
let tom: Person = {
id: 89757,
name: 'Tom',
gender: 'male'
};
tom.id = 9527; // error: ⽆法分配给'id',因为它是常量或只读属性
//错误案例使⽤⼆:
interface Person {
readonly id: number;
name: string;
age?: number;
[propName: string]: any;
}
// 在赋值的时候,属性id需要被初始化
/
/ error1:  Property 'id' is missing in type '{ name: string; gender: string; }
let tom: Person = {
name: 'Tom',
gender: 'male'
};
tom.id = 89757; //error2: Cannot assign to 'id' because it is a constant or a read-only property
结论(注意):只读的约束存在于第⼀次给对象赋值的时候,⽽不是第⼀次给只读属性赋值的时候
⼆、数组的类型
1.「类型 + ⽅括号」表⽰法
//ok(注意:数组的每⼀项类型必须保持⼀致)
let fibonacci: number[] = [1, 1, 2, 3, 5];
/
/error: Type '(string | number)[]' is not assignable to type 'number[]'
let fibonacci: number[] = [1, '1', 2, 3, 5];
//error: Argument of type '"8"' is not assignable to parameter of type 'number'.
let fibonacci: number[] = [1, 1, 2, 3, 5];
fibonacci.push('8');
2.数组泛型表⽰法
//ok (其注意事项与上⾯的基本表⽰保持⼀致)
let fibonacci: Array<number> = [1, 2, 2, 3, 5];
fibonacci.unshift(10);
3.数组接⼝表⽰法
// NumberArray 表⽰:只要 index 的类型是 number,那么值的类型必须是 number
interface NumberArray {
[index: number]: number;
}
let fibonacci: NumberArray = [1, 1, 2, 3, 5];
4.any在数组中的运⽤
let list: any[] = ['Xcat Liu', 25, { website: 'xcatliu' }];
5.类数组:arguments、NodeList、HTMLCollection等
function sum() {
let args: NodeList = ElementsByTagName('a');
}
三、函数的类型(* 核⼼)
1.函数的声明(包括函数声明和函数表达式)
//函数声明
function sum(x: number, y: number): number {
return x + y;
}
//函数表达式
let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
return x + y;
};
批注:(1)输⼊多余的(或者少于要求的)参数,是不被允许的(2)在 TypeScript 的类型定义中,=> ⽤来表⽰函数的定义,左边是输⼊类型,需要⽤括号括起来,右边是输出类型。
2.使⽤接⼝定义函数的形状
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
return source.search(subString) !== -1;
}
3.定义函数可选参数
function buildName(firstName: string, lastName?: string) {
if (lastName) {
return firstName + ' ' + lastName;
} else {
return firstName;
}
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');
批注:可选参数必须接在必需参数后⾯。换句话说,可选参数后⾯不允许再出现必须参数了。
4.设置函数参数默认值
function buildName(firstName: string, lastName: string = 'Cat') {
return firstName + ' ' + lastName;
}
let tomcat = buildName('Tom', 'Cat');
let tom = buildName('Tom');
5.多个不确定剩余参数
function push(array: any[], ...items: any[]) {
items.forEach(function(item) {
array.push(item);
});
}
let a = [];
push(a, 1, 2, 3);
6.函数的重载
function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {
if (typeof x === 'number') {
return String().split('').reverse().join(''));
} else if (typeof x === 'string') {
return x.split('').reverse().join('');
}
}
批注:上例中,我们重复定义了多次函数 reverse,前⼏次都是函数定义,最后⼀次是函数实现。在编辑器的代码提⽰中,可以正确的看到前两个提⽰。TypeScript 会优先从最前⾯的函数定义开始匹配,所以多个函数定义如果有包含关系,需要优先把精确的定义写在前⾯。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。