目录

 

一、对象的类型:接口
<https://blog.csdn.net/wu5229485/article/details/82771375#%E4%B8%80%E3%80%81%E5%AF%B9%E8%B1%A1%E7%9A%84%E7%B1%BB%E5%9E%8B%EF%BC%9A%E6%8E%A5%E5%8F%A3>

二、数组的类型
<https://blog.csdn.net/wu5229485/article/details/82771375#%E4%BA%8C%E3%80%81%E6%95%B0%E7%BB%84%E7%9A%84%E7%B1%BB%E5%9E%8B>

三、函数的类型(* 核心)
<https://blog.csdn.net/wu5229485/article/details/82771375#%E4%B8%89%E3%80%81%E5%87%BD%E6%95%B0%E7%9A%84%E7%B1%BB%E5%9E%8B%EF%BC%88*%20%E6%A0%B8%E5%BF%83%EF%BC%89>

一、对象的类型:接口


概述:在面向对象语言中,接口(Interfaces)是一个很重要的概念,它是对行为的抽象,而具体如何行动需要由类(classes)去实现(implements)

1.接口使用

这个例子中定义了一个接口 Person,接着定义了一个变量 tom,它的类型是 Person。这样,我们就约束了 tom 的形状必须和接口 Person 一致
//正确使用 interface Person { name: string; age: number; } let tom: Person = {
name: 'Tom', age: 25 }; // 错误案例一:定义的变量的属性比接口少 interface 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: 'http://xcatliu.com' }];
5.类数组:arguments、NodeList、HTMLCollection等
function sum() { let args: NodeList = document.getElementsByTagName('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 Number(x.toString().split('').reverse().join(''));  
  } else if (typeof x === 'string') {         return
x.split('').reverse().join('');     } }
批注:上例中,我们重复定义了多次函数
reverse,前几次都是函数定义,最后一次是函数实现。在编辑器的代码提示中,可以正确的看到前两个提示。TypeScript
会优先从最前面的函数定义开始匹配,所以多个函数定义如果有包含关系,需要优先把精确的定义写在前面。