【问题标题】:typescript return inferred type of assigned function, yet restrict the return type to extend predefined type打字稿返回分配函数的推断类型,但限制返回类型以扩展预定义类型
【发布时间】:2021-10-09 13:50:35
【问题描述】:

我正在编写许多函数(用于服务器请求),每个函数返回类型都扩展了某种类型。
我希望 typescript 限制返回类型以扩展预定义的已知类型,但我希望 typescript 采用返回类型的推断类型(因为它可能更准确)。

例如,假设所有函数都必须返回字符串,所以:

type myFuncsType = (...args: any) => string

每个函数都必须扩展这种类型。

现在假设我的函数总是返回一个常量字符串:

const myFunc1 = () => "MyString" as const
// the type is inffered:
const myVal = myFunc1()
// typeof myVal = "MyString"

我们还说过我们的函数必须扩展预定义的已知类型(myFuncsType),但是在分配类型时,通用类型会接管推断出的准确类型,这是我想避免的:

const myFunc1: myFuncsType = () => "MyString" as const
const myVal = myFunc1()
// typeof myVal = string

我尝试用泛型解决它,但是泛型需要传递预定义的类型,并且在声明期间返回类型不可用。

如何限制返回类型以扩展预定义类型,但返回从声明中推断出的确切返回类型?

【问题讨论】:

  • 您能否添加一个更完整的示例来说明您必须使用myFuncsType 的场景?

标签: typescript typescript-generics


【解决方案1】:

我们可以在声明期间获得函数的返回类型。

您可以使用内置的 typescript 实用程序之一ReturnType。该实用程序提供函数类型的返回类型。您可以阅读ReturnType 实用程序here 的更多示例。

type myFuncsType = (...args: any) => string
type FnReturnType = ReturnType<myFuncsType>;

您的问题:如何限制返回类型以扩展预定义类型,但返回从声明中推断出的确切返回类型?

我们先了解一下扩展类型(或赋值类型)和类型断言的区别。

const a: any = 20;
const b = a as number;
// typeof b is number

当我们将类型分配给我们的变量时,打字稿会知道并确认该变量的类型。

当我们有关于 TypeScript 无法知道的值类型的信息时,我们会使用 type assertion

因此,在回答您的问题时,将分配的类型和类型断言都分配给相同的值是没有意义的。如果你想做那个打字稿会说我比你更了解这种类型。

【讨论】:

    【解决方案2】:

    由于MyFuncsType 不是union,如果您annotate 具有该类型的myFunc1 变量,编译器将始终将该变量视为该类型。它不会根据分配给它的特定值来narrow 变量,而是将其一直加宽到带注释的类型。所以你不想注释myFunc1

    您真正想要做的不是注释,而是检查 myFunc1 可以分配给MyFuncsType,而不是扩大它。 TypeScript 中没有内置的运算符来执行此操作;有关此类功能的请求,请参阅microsoft/TypeScript#7481。但是您可以编写自己的辅助函数,其行为方式如下:

    type MyFuncsType = (...args: any) => string
    const asMyFuncsType = <T extends MyFuncsType>(t: T) => t;
    

    所以代替const f: MyFuncsType = ...,你改写const f = asMyFuncsType(...)asMyFuncsType() 函数只返回其输入而不更改其类型,但它确实检查该类型是否可分配给 MyFuncsType,因此它会捕获错误:

    const badFunc = asMyFuncsType(() => 123); // error!
    // -------------------------------> ~~~
    // Type 'number' is not assignable to type 'string'
    
    const myFunc1 = asMyFuncsType(() => "MyString" as const); // okay
    const myVal = myFunc1()
    // typeof myVal = "MyString"
    

    Playground link to code

    【讨论】:

    • 这是一个很好的解决方法,谢谢!但这很烦人,因为这会产生运行时后果。还是很好的答案
    猜你喜欢
    • 1970-01-01
    • 2015-08-10
    • 2022-01-12
    • 2021-10-04
    • 2020-05-09
    • 2018-02-22
    • 1970-01-01
    • 2020-06-29
    • 1970-01-01
    相关资源
    最近更新 更多