代码之家  ›  专栏  ›  技术社区  ›  Terry

使用枚举重载TypeScript函数

  •  1
  • Terry  · 技术社区  · 6 年前

    我在尝试使用TypeScript实现函数重载时遇到了一个小问题,该重载与作为参数传递的枚举以及类型取决于枚举的第二个参数结合使用。

    例如:

    • 如果枚举为 FOO string
    • 如果枚举为 BAR ,那么第二个参数是a number 类型
    • 如果枚举为 BAZ

    我的代码如下所示,但不知何故TypeScript抛出了一个错误,因为即使在我针对枚举检查第一个参数时,intellisense也不会缩小第二个参数的类型: fieldValue 总是 string | number

    enum ViewName {
        FOO = 'foo',
        BAR = 'bar',
        BAZ = 'baz'
    }
    
    function myFunction(viewName: ViewName.FOO, stringValue: string);
    function myFunction(viewName: ViewName.BAR, numberValue: number);
    function myFunction(viewName: ViewName.BAZ);
    function myFunction(viewName: ViewName, fieldValue?: string | number): void {
    
        if (viewName === ViewName.FOO) {
            fieldValue = fieldValue.reverse();
        }
    
        if (viewName === ViewName.BAR) {
            fieldValue *= 2;
        }
    
        if (viewName === ViewName.BAZ) {
            return console.log('No fieldvalue is supplied by BAZ.');
        }
    
        console.log(fieldValue);
    }
    

    也可以在上查看代码 TypeScript Playground .

    1 回复  |  直到 6 年前
        1
  •  6
  •   Titian Cernicova-Dragomir    6 年前

    Typescript不会根据第一个参数的类型缩小第二个参数的类型。这个特性只是没有在typescript中实现。

    if 让编译器缩小 fieldValue

    function myFunction(viewName: ViewName.FOO, stringValue: string);
    function myFunction(viewName: ViewName.BAR, numberValue: number);
    function myFunction(viewName: ViewName.BAZ);
    function myFunction(viewName: ViewName, fieldValue?: string | number): void {
    
        if (viewName === ViewName.FOO && typeof fieldValue === "string") {
            fieldValue = fieldValue.reverse();
        }
        else if (viewName === ViewName.BAR && typeof fieldValue === 'number') {
            fieldValue *= 2;
        }
    
        console.log(fieldValue);
    }
    

    也可以只使用类型断言:

    function myFunction(viewName: ViewName.FOO, stringValue: string);
    function myFunction(viewName: ViewName.BAR, numberValue: number);
    function myFunction(viewName: ViewName.BAZ);
    function myFunction(viewName: ViewName, fieldValue?: string | number): void {
    
        if (viewName === ViewName.FOO) {
            fieldValue = (fieldValue as string).reverse();
        }
        else if (viewName === ViewName.BAR) {
            fieldValue =  (fieldValue as number) * 2;
        }
    
        console.log(fieldValue);
    }
    

    更大的变化是使用有区别的联合,这将允许编译器以更期望的方式缩小参数的类型:

    function myFunction(p: { viewName: ViewName.BAZ }
        | { viewName: ViewName.BAR, fieldValue: number }
        | { viewName: ViewName.FOO, fieldValue: string }): void {
    
        if (p.viewName === ViewName.FOO) {
            p.fieldValue =  p.fieldValue.reverse();
        }
        else if (p.viewName === ViewName.BAR) {
            p.fieldValue *=  2;
        }
    
        console.log(fieldValue);
    }