目录
- // (a: string) => void 意味着 "有一个参数为string的函数,没有返回值"。
- function greeter(fn: (a: string) => void) {
- fn("Hello, World");
- }
-
- function printToConsole(s: string) {
- console.log(s);
- }
-
- greeter(printToConsole);
-
-
- // 使用类型别名定义函数
- let fun = (a:String) => void;
- function greeter(fn: fun){
- // ...
- }
在js中函数除了可以用来调用,函数还可以拥有属性。只是在函数类型表达式的语法不允许声明属性。 如果我们想用属性来描述可调用的东西,我们可以在一个对象类型中写一个调用签名。<与函数类型表达式相比,语法略有不同:在参数列表和返回类型之间使用 : 而不是 =>>
- type newDataType = {
- x: String,
- (a: String): Boolean //与函数类型表达式相比,语法略有不同:在参数列表和返回类型之间使用 : 而不是 =>
- }
-
- function handleFunction(fn: newDataType){
- console.log(fn.x + "return " + fn("hhh"))
- }
-
- function fn(str){
- return false
- }
- fn.x = "llllll"
-
- handleFunction(fn)
在js中函数可以通过new关键词来调用,这在js和ts中称之为构造函数;因为通过new出来的一般都是一个新对象。即可以通过在调用签名的前面添加new关键字来写一个构造签名
- class dataType{
- s: Number,
- constructor(s: Number){
- this.s = s;
- }
- }
-
- type newDataType = {
- new (s:Number): dataType
- }
-
- function handleType(dType: newDataType){
- return new dType(222);
- }
-
- console.log(handleType(dataType).s) // 打印出 222
在写一个函数时,输入的类型与输出的类型有关,或者两个输入的类型以某种方式相关,这是常见的。 在TypeScript中,当我们想描述两个值之间的对应关系时,会使用泛型。
- // 通过给这个函数添加一个类型参数 Type ,并在两个地方使用它,即已经在函数的输入(数组)和输出(返回值)之间建立了一个联系。现在调用它时,一个更具体的类型就出来了
- function firstArr<Type>(arr: Type<>){
- return arr[0];
- }
-
- // 调用函数
- // s 的类型这时候就为Number
- const s = firstArr([1,2,3,4])
-
- // s1 的类型这时候就为String
- const s1 = firstArr(['a','b','c','d'])
-
- // s2 的类型这时候就为undefined
- const s2 = firstArr([])
- // Type 约束为 { length: number } ,所以我们被允许访问 a 和 b 参数的 .length 属性。
- // 如果没有类型约束,我们就不能访问一些属性(会报错),因为这些值可能是一些没有长度属性的其他类型。
-
- function longest<Type extends { length: number }>(a: Type, b: Type) {
- if (a.length >= b.length) {
- return a;
- } else {
- return b;
- }
- }
- // longerArray 的类型是 'number[]'
- const longerArray = longest([1, 2], [1, 2, 3]);
-
- // longerString 是 'alice'|'bob' 的类型。
- const longerString = longest("alice", "bob");
-
- // 错误! 数字没有'长度'属性
- const notOK = longest(10, 100);
-
- // longerArray 和 longerString 的类型是根据参数推断出来的。
- // 泛型就是把两个或多个具有相同类型的值联系起来。
- function handelData<Type extends {length: Number}>(data: Type,flag: Number): Type{
- if(data.length > flag){
- return data
- } else{
- return {length: flag} // 错误,因为Type的类型不一定是个对象,即Type不一定要与其 限制值一致
- }
- }
-
- // 'arr' 获得值: { length: 6 }
- const arr = handelData([1, 2, 3], 6);
-
- // 错误,因为数组有一个'切片'方法,但对象没有
- console.log(arr.slice(0));
- // 指定函数返回的类型为Type[],但是在某些时候调用这个函数会出现错误
- function concatArray<Type>(a: Type[],b: Type[]): Type[]{
- return a.concat(b)
- }
-
- concatArray([1,2,3,4,5],["hello"]) // 报错,正常返回的类型推断的应该是 Number[],现在返回的是一个混合数组,所以函数应该这样更改
-
- concatArray<Number | String>([1,2,3,4,5],["hello"]) // 手动指定类型
- // 1、使用类型参数本身,而不是对其进行约束
- function firstElement1<Type>(arr: Type[]) {
- return arr[0];
- }
- function firstElement2<Type extends any[]>(arr: Type) {
- return arr[0];
- }
- // a: number (推荐)
- const a = firstElement1([1, 2, 3]);
- // b: any (不推荐)
- const b = firstElement2([1, 2, 3]);
-
-
- // 2、总是尽可能少地使用类型参数
- function filter1<Type>(arr: Type[], func: (arg: Type) => boolean): Type[] {
- return arr.filter(func);
- }
- // Func extends 就没有要的必要
- function filter2<Type, Func extends (arg: Type) => boolean>(
- arr: Type[],
- func: Func
- ): Type[] {
- return arr.filter(func);
- }
-
- // 3、如果一个类型的参数只出现在一个地方,请重新考虑你是否真的需要它
可选参数:在TypeScript的函数中,传递参数时,在参数的后面加上 ? 就表示该参数是可选参数。注意:虽然可选参数会被指定为某种类型,但该参数实际上将具有 某种类型 | undefined 类型,因为在 JavaScript中未指定的参数会得到 undefined 的值。
当为回调函数写参数是,一定要避免使用可选参数,除非你不打算使用这个参数。
在TypeScript中,我们可以通过编写重载签名来指定一个可以以不同方式调用的函数。要做到这一点, 要写一些数量的函数签名(通常是两个或更多)+ 函数的主体:
- 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); // 传递三个参数
- const d3 = makeDate(1, 3); // 错误,因为没有对应的重载函数签名与之对应
void 表示没有返回值的函数的返回值。当一个函数没有任何返回语句,或者没有从这些返回语句中返回任何明确的值时,它都是推断出来的类型。
unknown 类型代表任何值。这与 any 类型类似,但更安全,因为对未知 unknown 值做任何事情都是不合法的。 这在描述函数类型时很有用,因为你可以描述接受任何值的函数,而不需要在函数体中有 any 值。 反之,你可以描述一个返回未知类型的值的函数。
never 类型表示永远不会被观察到的值。在一个返回类型中,这意味着函数抛出一个异常或终止程序的执行。 never 也出现在TypeScript确定一个 union 中没有任何东西的时候。
- function multiply(n: number, ...m: number[]) {
- return m.map((x) => n * x);
- }
- // 'a' 获得的值 [10, 20, 30, 40]
- const a = multiply(10, 1, 2, 3, 4);
-
- // 展开数组
- const arr1 = [1, 2, 3];
- const arr2 = [4, 5, 6];
- arr1.push(...arr2);
-
- // ==============================参数解构==============================
-
- // 函数参数简写版
- function sum({ a, b, c }) {
- console.log(a + b + c);
- }
-
- // 详细版
- function sum({ a, b, c }: ABC) {
- console.log(a + b + c);
- }
-
- sum({ a: 10, b: 3, c: 9 })