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

Typescript:如何通过函数参数的值获取提取的联合类型的属性

  •  0
  • etblh  · 技术社区  · 1 年前

    我想知道是否有一种方法可以让ts编译器确定中的回调类型 useListenAPI 作为

    • (data: number[]) => void 如果事件类型===APIType。API1
    • (data: {isAdmin: boolean, data: number[]}) => void 如果事件类型===APIType。API2
    const enum APIType {
        API1 = 1,
        API2 = 2
    }
    
    interface API1{
        type: APIType.API1,
        Data: number[]
    }
    
    interface API2{
        type: APIType.API2,
        Data: {
            isAdmin: boolean,
            data: number[]
        }
    }
    
    type UnionAPI = API1 | API2;
    
    //ts error
    //'eventType' refers to a value, but is being used as a type here. Did you mean 'typeof eventType'?
    const useListenAPI = (eventType: APIType, callback: (data:Extract<UnionAPI,{type: eventType}>["Data"]) => void)) => {
        // do whatever
    }
    
    //'type: typeof eventType' will make callback is (data: number[]|{isAdmin: boolean, data: number[]}) => void
    const useListenAPI = (eventType: APIType, callback: (data:Extract<UnionAPI,{type: typeof eventType}>["Data"]) => void)) => {
        // do whatever
    }
    

    我知道使用泛型可以解决这个问题,如下所示,但我只是想知道是否有更简单的版本,或者它是ts编译器无法实现的,因为它是一个运行时的东西

    const useListenAPI = <T,>(eventType: APIType, callback: (data:Extract<UnionAPI,{type: T}>["Data"]) => void)) => {
        // do whatever
    }
    
    useListenAPI<APIType.API1>(APIType.API1, (data) => {
        // data: number[]
    })
    
    1 回复  |  直到 1 年前
        1
  •  1
  •   Hao-Jung Hsieh    1 年前

    您可以使用函数重载。

    下面是一个例子

    
    // Overloads
    function useListenAPI(eventType: APIType.API1, callback: (data: API1['Data']) => void): void;
    function useListenAPI(eventType: APIType.API2, callback: (data: API2['Data']) => void): void;
    function useListenAPI(eventType: APIType, callback: Function) {
        // implementation details
    }
    
    // Usage
    useListenAPI(APIType.API1, (data) => {
        // data is number[]
    });
    
    useListenAPI(APIType.API2, (data) => {
        // data is { isAdmin: boolean, data: number[] }
    });
    

    这是医生

    https://www.typescriptlang.org/docs/handbook/2/functions.html#function-overloads