gpt4 book ai didi

typescript - 如何根据输入参数键入返回类型

转载 作者:行者123 更新时间:2023-12-04 13:36:47 25 4
gpt4 key购买 nike

我有一个接收 options 的函数带有 kind 的参数属性。 kind 的可能值是一小组值。所以它基本上是一个枚举。

取决于 kind函数应该有不同的返回值。虽然所有可能的返回值都从一些常见的基本类型扩展而来。

我可以通过重载实现我想要的,但是函数本身的类型不是很好:

function test(options: Scenarios['bar']['options']): Scenarios['bar']['ret'];
function test(options: Scenarios['foo']['options']): Scenarios['foo']['ret'];
function test(options: any): any {
...
};

有没有一种使用泛型键入此内容的好方法?这将是完美的 if(options.kind === 'foo') { return ... }也会正确地强制执行正确的返回类型。

这就是我尝试过的,但它不起作用。
type Base {
a: string;
}

type Foo {
b: string;
}

type Bar {
c: string;
}

interface Scenarios {
foo: { options: { kind: 'foo', input: string }, ret: Foo },
bar: { options: { kind: 'bar' }, ret: Bar },
}

function test<S extends keyof Scenarios, O extends Scenarios[S]['options'], R extends Scenarios[S]['ret']>(options: O): R {
const out: Partial<R> = {
a: 'one',
};
if(options.kind === 'foo') {
out.b = options.input;
}
if(options.kind === 'bar') {
out.c = "whatever"
}

return out;
}

这里没有 O也不是 R似乎没有正确输入。我收到多个错误:
  • a: 'one',对象字面量错误可能仅指定已知属性,并且类型“部分”中不存在“a”
  • options.input类型“O”上不存在属性“输入”的错误。
  • out.b (和 out.c )类型“部分”上不存在属性“b”的错误。
  • 最佳答案

    我不是这方面的专家,但在根据您的要求玩了一段时间后,我意识到了一些事情:

  • TypeScript 只能区分联合类型;它不能区分泛型。
  • 所述歧视不会向上传播;也就是说,TypeScript 不会根据对子对象的区分来自动区分父对象。

  • 话虽如此,这是我想出的解决方案:
    type Base = { // I'm assuming this is the base type for Foo and Bar
    a: string;
    }

    interface Foo extends Base { // so I shall modify here a bit
    b: string;
    }

    interface Bar extends Base { // and here of course
    c: string;
    }

    interface Scenarios {
    // Now I put the return type inside the option, to make the discrimination work
    // Of course, I need to make 'ret' optional, or your input won't make sense
    foo: { kind: 'foo', input: string, ret?: Foo },
    bar: { kind: 'bar', ret?: Bar },
    }

    // Notice the use of 'Required' here; that brings the actual type of 'ret' back
    function test<X extends keyof Scenarios>(options: Scenarios[X]): Required<Scenarios[X]>['ret'] {
    let data = options as Scenarios[keyof Scenarios]; // create a union type
    data.ret = { a: 'one' } as Scenarios[keyof Scenarios]['ret']; // type assertion

    if (data.kind === 'foo') {
    data.ret!.b = data.input; // finally the discrimination works!
    }
    if (data.kind === 'bar') {
    data.ret!.c = "whatever"
    }
    return data.ret!;
    }

    好的,到目前为止一切顺利,不幸的是我仍然无法让 TypeScript 自动推断泛型参数。说如果我跑:
    var result = test({ kind: 'foo', input: "aas" }); // oops

    然后 TypeScript 仍然无法弄清楚 result类型为 Foo .但是,当然,这种自动推理的实际值(value)非常低,因为即使它有效,它也只有在您在函数的参数中逐字键入“foo”一词时才有效,并且如果您可以这样做,什么阻止你输入泛型参数?

    您可以在此 Playground Link 中尝试这些代码

    更新:

    我刚刚找到了我最后一个问题的解决方案:
    function test<X extends keyof Scenarios>(options: { kind: X } & Scenarios[X]): Required<Scenarios[X]>['ret'] {
    ....
    }

    var result = test({ kind: 'foo', input: "aas" }); // It works!

    诀窍是添加 { kind: X }到参数声明。

    看到这个 Playground Link .

    关于typescript - 如何根据输入参数键入返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61368548/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com