函数类型
TS定义函数类型需要定义输入类型和输出类型,其中输出类型可以忽略不写,因为TS能够根据返回的语句自动推断出返回的类型,这与Go语言自动推断类型很像。
定义简单的函数
// 定义输入类型和输出类型
function add(val1: number, val2: number): number {
return val1 + val2
}
// 定义输入类型而不定义输出类型,将自动推到出输出类型
function add1(val1: number, val2: number) {
return val1 + val2
}
返回void类型
// 写输出类型为void类型
function get(): void {
console.log("hello world")
}
// 不写输出类型,也能自动推导出void类型
function get() {
console.log("hello world")
}
箭头函数
const add = (val1: number, val2: number): number => {
return val1 + val2
}
可选参数
const add = (val1: number, val2: number, val3?: number): number => {
return val1 + val2
}
console.log(add(1,2))
console.log(add(1,2,3))
默认参数
function add(val1: number = 1, val2: number = 2){
return val1 + val2
}
console.log(add()) // 3
类型别名定义函数类型
type MyFunctionType = (param1:string,param2:number) => boolean
const MyFunction:MyFunctionType = (param1,param2) => {
// 判断param1和param2的类型是否相等
if(typeof param1 === typeof param2){
return true
}
return false
}
接口定义函数类型
interface MyFunctionInterface {
(param1: number, param2: string): boolean;
}
const MyFunction: MyFunctionInterface = (param1, param2) => {
// 判断param1和param2的类型是否相等
if (typeof param1 === typeof param2) {
return true
}
return false
}
接口
在 TypeScript 中,interface(接口)用于定义对象的类型。它可以描述对象的结构,包括属性和方法。
定义 interface
一般首字母大写,代码如下:
interface Person {
name: string;
age: number;
sayHello: () => void;
}
注意:当定义完interface
后,属性和类型定义必须完全一致
// 例如少写了sayHello方法,提示类型报错 "{ name: string; age: number; }" 中缺少属性 "sayHello",但类型 "Person" 中需要该属性。
let person: Person = {
name: 'Tom',
age: 20,
};
// 当多添加字段phone的时候,提示类型报错 不能将类型“{ name: string; age: number; sayHello: () => void; phone: string; }”分配给类型“Person”。对象字面量只能指定已知属性,并且“phone”不在类型“Person”中。
let person: Person = {
name: 'Tom',
age: 20,
sayHello: function () {
console.log('Hello ' + this.name);
},
phone: '123-456-7890'
};
可选属性
在 TypeScript 的接口中,我们可以定义可选属性。可选属性表示该属性可以存在,也可以不存在,对象可以选择性地包含这些属性。
我们可以通过在属性名后加上问号(?)来定义可选属性。下面是一个示例:
interface Person {
name: string;
age?: number;
sayHello: () => void;
}
在上面的示例中,age
属性被定义为可选属性,即对象可以有也可以没有 age
属性。
当我们创建对象时,可以选择性地包含可选属性。下面是一个示例:
const tom: Person = {
name: "Tom",
sayHello: () => {
console.log(`Hello, my name is ${this.name}`);
}
};
在上面的示例中,我们创建了一个名为 tom 的对象,它包含了 name 属性和 sayHello 方法,但是没有 age 属性。
索引签名(自定义属性)
在 TypeScript 中,接口(interface)可以定义索引签名,用于描述对象的索引类型和对应的属性类型
索引签名允许对象具有动态属性,这意味着可以使用可变的键来访问和设置属性。有两种类型的索引签名:字符串索引签名和数字索引签名。
以下是一个使用字符串索引签名的示例:
interface Person {
name: string;
age: number;
[key: string]: string | number;
}
const person: Person = {
name: "Tom",
age: 25,
Email: "123456@qq.com",
gender: "Man"
};
console.log(person.name); // 输出: John
console.log(person.age); // 输出: 25
console.log(person.Email); // 输出: 123456@qq.com
console.log(person.gender); // 输出: Man
在上述代码中,我们定义了一个 Person
接口,其中的 key
是字符串类型的索引签名,表示可以使用任意字符串作为对象的属性名,对应的属性值类型是 string
或 number
。
通过使用字符串索引签名,我们可以在创建对象时动态地添加任意的属性,并且保证这些属性的值的类型是 string
或 number
。
另外,还可以使用数字索引签名
来定义数组类型
的接口,以下是一个使用数字索引签名的示例:
interface NumberArray {
[index: number]: number;
}
const numbers: NumberArray = [1, 2, 3, 4, 5];
console.log(numbers[0]); // 输出: 1
console.log(numbers[1]); // 输出: 2
console.log(numbers[2]); // 输出: 3
只读属性
在 TypeScript 中,可以使用 readonly 关键字来定义只读属性,它用于确保某个属性只能在创建对象时进行赋值,而不能在之后进行修改。
下面是一个使用 readonly
定义只读属性的示例:
interface Person {
readonly name: string;
age: number;
}
const person: Person = {
name: "Tom",
age: 25
};
console.log(person.name); // 输出: Tom
// 以下代码会引发错误
person.name = "Dadong"; // 不能修改只读属性
person.age = 30; // 可以修改非只读属性
console.log(person.age); // 输出: 30
在上述代码中,我们定义了一个 Person 接口,其中的 name 属性使用 readonly 关键字标记为只读属性。在创建对象 person 时,可以对只读属性进行赋值,但之后无法修改。
在使用只读属性时,需要注意以下几点:
只读属性必须在对象的创建时进行赋值,之后不能再对其进行修改。
只读属性只能在对象内部进行赋值,而不能在外部进行赋值。
如果将只读属性作为函数参数或返回值,那么在函数内部也不能对其进行修改。
通过使用 readonly 关键字,可以提升代码的安全性,并确保对象的某些属性不会在运行时被意外修改。
接口的继承
在 TypeScript 中,接口(interface)可以通过继承(extends)其他接口来扩展其属性和方法。
接口的继承使用 extends 关键字,可以继承单个或多个其他接口。被继承的接口称为父接口,继承它的接口称为子接口。
下面是一个使用接口继承的示例:
interface Animal {
name: string;
sound: string;
}
interface Dog extends Animal {
breed: string;
}
const myDog: Dog = {
name: "Max",
sound: "Woof",
breed: "Labrador"
};
console.log(myDog.name); // 输出: Max
console.log(myDog.sound); // 输出: Woof
console.log(myDog.breed); // 输出: Labrador
在上述代码中,我们定义了一个 Animal
接口,它包含 name
和 sound
属性。然后我们定义了一个 Dog
接口,它继承了 Animal
接口,并添加了一个 breed
属性。
通过继承 Animal
接口,Dog
接口拥有了 name
和 sound
属性,同时还有自己的 breed
属性。
我们创建了一个 myDog
对象,它符合 Dog
接口的定义,并可以访问 name
、sound
和 breed
属性。
可以使用继承来创建更具体的接口,通过继承的方式复用已有的接口定义,并在其基础上添加、修改或扩展属性和方法,使代码更加模块化和可维护。
接口合并
在 TypeScript 中,可以通过接口合并来扩展已有接口的定义。当多个同名接口出现时,它们会自动合并为一个接口。
接口合并可以用于在不同的地方对同一个接口进行扩展,以实现接口的分离和模块化。
以下是一个示例:
interface Animal {
name: string;
sound: string;
}
interface Animal {
age: number;
}
const myAnimal: Animal = {
name: "Max",
sound: "Woof",
age: 3
};
console.log(myAnimal.name); // 输出: Max
console.log(myAnimal.sound); // 输出: Woof
console.log(myAnimal.age); // 输出: 3
在上述代码中,我们定义了两个同名的接口 Animal
,它们分别包含不同的属性。当我们创建一个 myAnimal
对象时,它会同时具有两个接口的属性。
接口合并的规则如下:
属性的类型必须匹配。如果同名属性的类型不一致,则会产生编译错误。
同名函数接口会被合并为一个函数接口。合并后的函数接口包含了所有同名函数的定义,且函数重载也会被保留。
同名方法签名会被合并为一个方法签名。合并后的方法签名包含了所有同名方法签名的参数和返回类型。
接口合并在
TypeScript
中提供了一种灵活的方式来对接口进行扩展和组合,可以根据需求灵活使用。