typescript 返回union参数键的类型脚本泛型函数

t1qtbnec  于 2023-02-20  发布在  TypeScript
关注(0)|答案(1)|浏览(111)

我想写一个返回一个对象的函数,它的键基于参数。我希望它是静态类型的,并且我认为它应该是可能的,因为值在传递时就存在了。下面是一个例子:

type ResponseKeys = 'a' | 'b';

interface A {
    city: string;
}

interface B {
    town: string;
}

interface Result<T> {
    data: T | null;
}

function transform<T>(operationName: ResponseKeys): { [operationName in ResponseKeys]?: Result<T> } {
    return {
        [operationName]: {
            data: null,
        },
    };
}

console.log(transform<A>('a'));

在Typescript操场上尝试一下
我得到了想要的函数响应,但是transform()的类型签名是:

{
    a?: Response<A> | undefined;
    b?: Response<A> | undefined;
}

我希望将其范围缩小并更好地界定为:

{
    a: Response<A>;
}

即,仅具有指定的键,并且它不是与undefined的并集。

f4t66c6m

f4t66c6m1#

有两个不同的问题:
1.您需要在响应密钥('a ')和转换结果(A)之间进行绑定。
1.在这种情况下,Typescript不能很好地处理计算属性(参见https://github.com/microsoft/TypeScript/issues/41779
一种解决方案是通过重载签名来处理这两个问题:

function transform(operationName: 'a') : {a: Result<A>};
function transform(operationName: 'b') : {b: Result<B>};

function transform<T>(operationName: ResponseKeys) : {[key: string]: Result<T>} {
    if (operationName === "a") {
        return {a: {data: null}};
    } else {
        return {b: {data: null}};
    }
}

const resultA: {a: Result<A>} = transform('a');
const resultB: {b: Result<B>} = transform('b');

另一种方法是通过类型Assert为#1提供显式绑定并强制#2:

type TransformType<K extends ResponseKeys> = {a: A, b: B}[K];
type ResponseResult<K extends ResponseKeys> = Record<K, Result<TransformType<K>>>;

function transform<K extends ResponseKeys>(operationName: K) : ResponseResult<K> {
    return {[operationName] : {data: null}} as ResponseResult<K>;
}

const resA: ResponseResult<'a'> = transform('a');
const resB: ResponseResult<'b'> = transform('b');

相关问题