• 极客时间
    2019-07-22
    主要讲了定义函数类型的三种方式
    1、使用变量的方式
    2、使用type(类型别名)
    3、使用inerface (接口)

    使用interface还可以定义混合类型,俗称类库,这个类型的变量既可以当做函数使用,并且其本身还有一些属性或者方法,类似jquery的$使用方式。
    但是使用interface定义混合类型(类库):
    需要注意,其第一个行或者第一个属性必须是一个匿名函数。

    形式如下:
    interface App{
        ():void,
        dosomething():void,
        version:string
    }

    后面如果使用这个类型定义变量的话,一般需要类型断言,使用as。

    使用如下:

    let app:App = (()=>{}) as App;
    app.version = 1.0;
    app.dosomething = ()=>{};

    这个过程可以封装成一个工厂函数:

    function getapp(){
    let app:App = (()=>{}) as App;
    app.version = 1.0;
    app.dosomething = ()=>{};
    return app
    }
    let app = getapp()

    这里有个疑问:我看文档type是类型别名的意思,type和interface在使用场景上有啥区别呢?
    展开

    作者回复: type:不创建新的类型,只是给一个类型起一个名字,比如联合类型,写起来不方便,用type定义后就很简洁,你可以把type当做一种快捷访问方式;

    interface:创建新的类型,接口之间还可以继承(type不可以)。如果可能,建议优先使用 interface。

    另外纠正你的一个理解,接口中的属性没有顺序之分,混合接口不需要第一个属性是匿名函数。

    
     5
  • 极客时间
    2019-07-24
    在C++或者java等静态语言中,两个函数名称相同,但是参数类型不同或者参数个数不同,实现了函数重载。
    函数重载的好处是:不需要为功能相似的函数起不同的名称。

    ts实现函数重载的时候,要求定义一系列的函数声明,在类型最宽泛的版本中实现重载,最宽泛的版本个人理解应该是,参数是any类型 返回值是any类型,如下

    ```
    function add8(...rest: any[]): any {
        let first = rest[0];
        if(typeof first === 'string') {
            return rest.join('')
        }
        if(typeof first === 'number') {
            return rest.reduce((pre, cur) => pre + cur)
        }
    }
    ```

    这里有个疑问? 如果这样调用会报错吗 add8(),不传递任何参数
    如果不报错,为什么呢?

    add8(...rest: any[]) 这样定义函数是否包含了未传参数的情况呢?
    展开

    作者回复: 剩余参数表示参数个数不确定,不传是可以的,函数返回的是 undefined。可以加入判断 undefined 的逻辑:
    if (typeof first === 'undefined') {
            throw new Error('No param')
    }

    
     4
  • 盛世华夏
    2019-09-12
    function func6(x:number,y=1,z:number,q=1){
        return x+y+z+q;
    }
    console.log(func6(1,undefined,3)); //6 第二个参数undefined的时候3这个参数没有传给y,而是传给了z,y使用了默认值
    
     3
  • TechCheng
    2019-08-13
    function add8(...rest: number[]): number;
    function add8(...rest: string[]): string;
    function add8(...rest: number[] | string[]): number | string {
      let first = rest[0]
      if (typeof first === 'string') {
        return rest.join('')
      }
      if (typeof first === 'number') {
        return rest.reduce((pre, cur) => pre + cur)
      }
    }
    console.log(add8(1,2,3))
    为啥会报错
    展开

    作者回复: 函数重载一般在实现时用any类型,如果一定要这么些,有两个报错要处理:
    1)返回值类型加上undefined
    2)第二个分支,给rest加上类型断言 (rest as number[]),ts只推断了first,rest类型还是 number[]|string[],不符合reduce的接口声明

     1
     2
  • 麦晓杰alwaysu
    2019-07-23
    四种声明方式:
        1. 通过function
        2. 通过变量
        3. 通过接口
        4. 通过类型别名

    可选参数:
    通过 ? 来声明。
    ```typescript
    function add5(x: number, y?: number) {
        return y? x + y : x;
    }
    ```

    剩余参数
    ```typescript
    function add6(x: number, ... rest: number[]) {
        return x + rest.reduce((pre, cur) => pre + cur)
    }
    ```
    参数默认值:
    ```typescript
    function add7(x: number, y = 0, z: number, q =1) {
        return x + y + z + q;
    }
    add6(1, undefined, 3)
    ```
    注意:
    必选参数前面的默认参数是不可省略的,需传入 undefined 来获取它的默认值;
    必选参数后面的默认参数是可以省略的。

    函数重载
    ```typescript
    function add8(...rest: number[]): number;
    function add8(...rest: string[]): string;
    function add8(...rest: any[]): any {
        let first = rest[0];
        if(typeof first === 'string') {
            return rest.join('')
        }
        if(typeof first === 'number') {
            return rest.reduce((pre, cur) => pre + cur)
        }
    }
    ```

    ps: 极客时间留言板不支持md是有些难受的😣
    展开
    
     2
  • kevinInsight
    2019-08-25
    请教下老师:

    let addFun:(a:number,b:number)=>number

    这种函数定义的方式,在实际调用的时候该怎么使用?

    作者回复: 这是函数类型的定义,调用前还需要有实现,比如:addFun = (a, b) => a + b;
    然后再调用:addFun(1, 2)

    
     1
  • uinging
    2019-08-18
    有一个小点, arr.reduce() 方法视频里并没有传入初始值, 这样在空数组的时候会报错. 传入初始值 0 就好了.

    作者回复: if (typeof first === 'number') 已经保证了rest 不会是空数组

     1
     1
  • 安冬
    2019-08-14
    听到函数重载时,也遇到参数为空时的困惑,当时是这样处理的:
    ```typescript
    function MySum(...rest: number[]): number;
    function MySum(...rest: string[]): string;
    function MySum(...rest: any[]): any {
        return typeof rest[0] === 'number' ? rest.reduce((pre, cur) => (pre + cur)) :
                typeof rest[0] === 'string' ? rest.join("") : undefined;
    }
    console.log( MySum(1, 2, 3, 4, 5) ); // 15
    console.log( MySum('1', '2', '3', 'a', 'b') ); // 123ab
    console.log( `MySum() = ${MySum()}` ); // MySum() = undefined
    ```
    另外想请教老师,TypeScript 中是否不要求使用分号结尾?视频中好像都没作特别要求?
    展开

    作者回复: 视频中没有处理参数未定义的情况,你这样处理可以。
    ts中对分号结尾没有要求,这个全看个人风格。

    
     1
  • Human
    2019-08-03
    3被赋值给z,不是y

    function add6(x: number, y = 0, z: number, q = 1) {
      return x + y - z + q
    }
    console.log(add6(1, undefined, 3))
    -1
    展开
    
     1
  • lf
    2019-11-13
    function sum6(a:number, b=2, c:number, d=4) {
        return a+b+c+d
    }
    console.log(sum6(undefined, undefined, 3), 'sum6(1, undefined, 3)') // 10 1 + 3 + 4

    第一个参数为undefined,不报错,这是因为之前说的,undefined是所有类型的子集的原因吗?
    展开

    作者回复: 第一个参数是undefined应该报错,仔细看一下,或重启一下VSCode

    
    
  • Its me
    2019-08-28
    老师,函数的重载部分我有一些疑问
    为什么要多余的定义两个函数呢
    function add8(...rest: number[]): number
    function add8(...rest: string[]): string
    直接定义一个
    function add8(...rest: any[]): any
    不是就可以实现函数的重载了吗
    而且我从TypeScript的官网编译结果来看,没有丝毫差别呀
    编译结果如下:
    function F4() {
        var rest = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            rest[_i] = arguments[_i];
        }
        var first = rest[0];
        if (typeof first === 'number') {
            return rest.reduce(function (pre, cur) { return pre + cur; });
        }
        if (typeof first === 'string') {
            return rest.join(',');
        }
    }
    展开

    作者回复: 为啥用函数重载,请见本节我对 火云邪神0007 的回复。
    因为不是很方便,函数重载在实际应用中使用的比较少,一般会用联合类型或泛型代替。
    另外,函数重载的声明只用于类型检查阶段,在编译后会被删除。

    
    
  • 火云邪神0007
    2019-08-21
    // function add3(...rest: number[]): number
    // function add3(...rest: string[]): string
    function add3(...rest: any[]): any {
      if(typeof rest[0] === 'number') return rest.reduce((pre, cur) => pre + cur)
      if(typeof rest[0] === 'string') return rest.join('')
    }
    document.getElementById('app').innerHTML = add3(1, 2, 3, 4, 5).toString()

    老师,这样也跑的通,是不是没必要写前面的number和string的定义啊
    展开

    作者回复: 我们的目的不是为了跑通,而要理解函数重载的意义,前两条声明是重载,目的是将参数类型约束为 number 或 string;最后的实现不是重载,要遵循前面的声明,比如传 boolean 就不可以了。

    
    
  • Silence
    2019-07-25
    let Add1: (x: number, y: number) => number

    这个能干啥?好像也不能实现函数。

    作者回复: 这是定义一个函数类型,函数实现可基于此类型。

     3
    
我们在线,来聊聊吧