上一篇介绍了 Generic 泛型, 其实这篇差不多意思 XDD 主要针对 Generic Function。
若有错误,欢迎留言指教,感恩的心。
以下例子想要取得带入参数 array 第0个的值, 我们可以看到s
回传值的型别会是 any
, 但我想要带入不同的值对应的型别,该怎麽做呢。
function firstElement(arr: any[]) {
return arr[0];
}
const s = firstElement(["a", "b", "c"]);
const n = firstElement([1, 2, 3]);
console.log(s); //a
console.log(n); //1
我们可以使用泛型,我们在函式名後添加了 ,其中 Type 用来指代任意输入的型别,让型别推论自动推算出来。 可以看到变数s
会是string型别。而n
会是number型别。
function firstElement<Type>(arr: Type[]): Type {
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]);
console.log(s); //a
console.log(n); //1
除了使用<Type>
的方式, 可以传入多组参数如<Input, Output>
,让 TypeScript 自动 inferred 型别。
如下,n
被 inferred 为 string
, 而透过 parseInt 字串转数字,最後 parsed
被 inferred 的型别是 number[]
。 Input
及Output
命名可以自行定义。
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, 10));
console.log(parsed); //[1,2,3]
以下函式有两个传入参数 a
及 b
, 我们预期他们传入的型别都要有 length
属性,我们这时候可以使用 extends
关键字来限制参数length
属性,且指定length
是 number 型别。
我们可以看到只有 notOK 会报错,因为传入的参数 (10, 100)
不符 length
属性。
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]);
console.log(longerArray); //[1,2,3]
// longerString is of type 'alice' | 'bob'
const longerString = longest("alice", "bob");
console.log(longerString); //alice
// Error! Numbers don't have a 'length' property
const notOK = longest(10, 100);
//error: Argument of type 'number' is not assignable to parameter of type '{ length: number; }'.
在官网有举例在使用generic泛型约束的时候,可能会出错的地方,可参考 这里。
在使用 generic 中有些情况 TypeScript 无法自动inferred型别,我们可以自行指定:
function combine<Type>(arr1: Type[], arr2: Type[]): Type[] {
return arr1.concat(arr2);
}
const arr = combine([1, 2, 3], ["hello"]);
//❌ error: Type 'string' is not assignable to type 'number'.
const arr = combine<string | number>([1, 2, 3], ["hello"]);
console.log(arr); //[1, 2, 3, "hello"]
// ⭕ 指定他为 string | number 联合型别。
//⭕ 返回型别为 Type
function firstElement1<Type>(arr: Type[]) {
return arr[0];
}
//❌ 返回型别为 any
function firstElement2<Type extends any[]>(arr: Type) {
return arr[0];
}
// a: number (good)
const a = firstElement1([1, 2, 3]);
// b: any (bad)
const b = firstElement2([1, 2, 3]);
Always use as few type parameters as possible.
//⭕
function filter1<Type>(arr: Type[], func: (arg: Type) => boolean): Type[] {
return arr.filter(func);
}
//❌
function filter2<Type, Func extends (arg: Type) => boolean>(
arr: Type[],
func: Func
): Type[] {
return arr.filter(func);
}
If a type parameter only appears in one location, strongly reconsider if you actually need it.
如果只使用到一种型别,我们应该用简单的方式去写即可。
//❌
function greet1<Str extends string>(s: Str) {
console.log("Hello, " + s);
}
greet1("world");
//⭕
function greet2(s: string) {
console.log("Hello, " + s);
}
greet2("world");
Day22 done. 感谢阅读,明天见!
https://www.typescriptlang.org/docs/handbook/2/functions.html#generic-functions
<<: 【在厨房想30天的演算法】Day 22 演算法 : 最短路径 Shortest Path Bellman–Ford 演算法
>>: 成为工具人应有的工具包-22 OpenedFilesView
以前我绝对是对哲学避之唯恐不及的 但某一年意外看到「正义 一场思辨之旅」以及「超译 尼采」後 开始...
如果说可以让模型缩小10倍,精度还维持水准,这是什麽巫术? 延续 Day 20 的模型优化作法,本...
首先先在plugins/底下创立一个档案叫做ActionBattle_Actor.js 接着用昨天的...
工业控制网路 vs IT 资讯网路 管理目标 工业控制网路的设备需要高可用性,因为工厂设备若停摆,...
Day3 软件架构 这边卡比要介绍一个名词, Software Architecture 软件架构。...