TypeScript-02基础知识之函数

目录

1、函数类型表达式

2、调用签名

 3、构造签名

4、泛型函数

        函数泛型的限制条件

        约束条件中常见的错误使用

5、指定类型参数

6、优秀函数编写的准则

7、函数参数的应用

8、函数的重载

9、其他类型

10、参数扩展运算符 与 参数解构


 

1、函数类型表达式

// (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){
    // ...
}

2、调用签名

        在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)

 3、构造签名

        在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

4、泛型函数

        在写一个函数时,输入的类型与输出的类型有关,或者两个输入的类型以某种方式相关,这是常见的。  在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));

5、指定类型参数

// 指定函数返回的类型为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"]) // 手动指定类型

6、优秀函数编写的准则

// 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、如果一个类型的参数只出现在一个地方,请重新考虑你是否真的需要它

7、函数参数的应用

可选参数:在TypeScript的函数中,传递参数时,在参数的后面加上 ? 就表示该参数是可选参数。注意:虽然可选参数会被指定为某种类型,但该参数实际上将具有 某种类型 | undefined 类型,因为在 JavaScript中未指定的参数会得到 undefined 的值。

        当为回调函数写参数是,一定要避免使用可选参数,除非你不打算使用这个参数。

8、函数的重载

        在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);       // 错误,因为没有对应的重载函数签名与之对应

9、其他类型

        void 表示没有返回值的函数的返回值。当一个函数没有任何返回语句,或者没有从这些返回语句中返回任何明确的值时,它都是推断出来的类型。

        unknown 类型代表任何值。这与 any 类型类似,但更安全,因为对未知 unknown 值做任何事情都是不合法的。 这在描述函数类型时很有用,因为你可以描述接受任何值的函数,而不需要在函数体中有 any 值。 反之,你可以描述一个返回未知类型的值的函数。

        never 类型表示永远不会被观察到的值。在一个返回类型中,这意味着函数抛出一个异常或终止程序的执行。 never 也出现在TypeScript确定一个 union 中没有任何东西的时候。 

10、参数扩展运算符 与 参数解构

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 })
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BlackStar-Coder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值