函数类型
type GreetFunction = (a: string) => void;
function greeter(fn: GreetFunction) {
// ...
}
调用签名
type DescribableFunction = {
description: string;
// 是对象类型,所以是`:`,而不是`=>`
(someArg: number): boolean;
};
function doSomething(fn: DescribableFunction) {
console.log(fn.description + " returned " + fn(6));
}
函数可以有自己的属性,但是函数类型表达式不能声明属性,可以使用对象类型来表示调用签名。
构造签名
js中的函数可以通过new
操作符来当做构造函数调用。
type SomeConstructor = {
// 调用签名前添加new
new (s: string): SomeObject;
};
function fn(ctor: SomeConstructor) {
return new ctor("hello");
}
还有一些对象,既可以当做普通函数调用,也可以当做构造函数调用,比如像Date
。
interface CallOrConstruct {
new (s: string): Date;
(n?: number): number;
}
泛型函数
在ts中,泛型用来描述2个值之间的一致性。使用Type
类型参数,使入参出参建立了联系。调用时,ts可以推断出更具体的类型。
function firstElement<Type>(arr: Type[]): Type | undefined {
return arr[0];
}
// s is of type 'string'
const s = firstElement(["a", "b", "c"]);
// n is of type 'number'
const n = firstElement([1, 2, 3]);
// u is of type undefined
const u = firstElement([]);
接口
function map<Input, Output>(arr: Input[], func: (arg: Input) => Output): Output[] {
return arr.map(func);
}
// Parameter 'n' is of type 'string'
// 'parsed' is of type 'number[]'
const parsed = map(["1", "2", "3"], (n) => parseInt(n));
类型约束
可以使用extends
来约束泛型类型
function longest<Type extends { length: number }>(a: Type, b: Type) {
if (a.length >= b.length) {
return a;
} else {
return b;
}
}
// longerArray is of type 'number[]'
const longerArray = longest([1, 2], [1, 2, 3]);
// longerString is of type 'alice' | 'bob'
const longerString = longest("alice", "bob");
// Error! Numbers don't have a 'length' property
const notOK = longest(10, 100);
指定参数类型
function combine<Type>(arr1: Type[], arr2: Type[]): Type[] {
return arr1.concat(arr2);
}
// Type 'string' is not assignable to type 'number'.
const arr = combine([1, 2, 3], ["hello"]);
// 手动指定类型
const arr = combine<string | number>([1, 2, 3], ["hello"]);
参数可选
function f(x?: number) {
// ...
}
f(); // OK
f(10); // OK
重载
function makeDate(timestamp: number): Date;
function makeDate(m: number, d: number, y: number): Date;
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
if (d !== undefined && y !== undefined) {
return new Date(y, mOrTimestamp, d);
} else {
return new Date(mOrTimestamp);
}
}
const d1 = makeDate(12345678);
const d2 = makeDate(5, 5, 5);
多个重载签名,一个实现签名(需要兼容重载签名)
申明this
interface DB {
filterUsers(filter: (this: User) => boolean): User[];
}
const db = getDB();
const admins = db.filterUsers(function (this: User) {
return this.admin;
});
有些场景下,ts不能推导出this的指向,js规范规定不能使用this
关键字当作形参,所以ts利用了这点,可以在入参中使用this关键字声明函数体中this的类型。
其他类型
void
函数没返回值,ts中void
与undefined
不一样。
object
object
类型可以表示除了基本数据类型(string
, number
, bigint
, boolean
, symbol
, null
, undefined
)外的任何类型。ts中函数也可以是object
类型。
unknown
unknow
类型可以代表任何一种类型,但是比any
类型要安全。
never
function fail(msg: string): never {
throw new Error(msg);
}
Function
function doSomething(f: Function) {
return f(1, 2, 3);
}
避免使用,返回值是any类型。一般使用() => void
剩余参数、Arguments
function multiply(n: number, ...m: number[]) {
return m.map((x) => n * x);
}
// 'a' gets value [10, 20, 30, 40]
const a = multiply(10, 1, 2, 3, 4);
const args = [8, 5] as const;
// OK
const angle = Math.atan2(...args);
参数解构
function sum({ a, b, c }: { a: number; b: number; c: number }) {}
// 或者
type ABC = { a: number; b: number; c: number };
function sum({ a, b, c }: ABC) {}
Assignability of Functions
type voidFunc = () => void;
const f1: voidFunc = () => {
return true;
};
const f2: voidFunc = () => true;
const f3: voidFunc = function () {
return true;
};
当函数的类型是type vf = () => void
,实现时可以返回任何一个值。
function f2(): void {
// @ts-expect-error
return true;
}
const f3 = function (): void {
// @ts-expect-error
return true;
};
定义函数时,返回类型是void时,不能返回任何值,否则ts会报错。