【问题标题】:How to enforce narrowing to specific type of a typed const in typescript?如何在打字稿中强制缩小到特定类型的类型化 const?
【发布时间】:2021-02-01 12:34:44
【问题描述】:

我的问题是是否可以使用 typeof 来推断 const 变量的实际类型,而不依赖于定义的更广泛的类型?

如果您假设嵌套对象看起来像一棵树并且简单属性是叶子。然后我想有一种方法来定义子树。

我想在使用in keyof 的泛型中使用它,并且只想迭代明确提到的键,而不是类型定义的所有隐含键。在下面的示例中,我需要 keyof typeof a 不包括 barbaz

示例

这个想法是Base 类型旨在定义变量a 的“最大扩展”的可能结构,并允许在编写a 时使用自动补全。

一旦a 被定义,它就有自己的更窄的类型,我想稍后用它来过滤某些键。

type Base = {
    foo?: string;
    bar?: string;
    baz?: string;
}

const a: Base = {
    foo: '123',
};

const a_typeof: typeof a = {
    foo: '123',
    bar: '123', // I want this to be wrong
};

我知道,由于我将 a 定义为 Base 类型,因此它们等于 type of a == Base,但我希望 typeof a = { foo: string }{ foo: string } 是更窄的 Base 类型。

特别是,如果我从a 的定义中删除: Base,我会得到想要的效果。

const b = {
    foo: '123',
};

const b_typeof: typeof b = {
    foo: '123',
    bar: '123',
//  ^: Type '{ foo: string; bar: string; }' is not assignable to type '{ foo: string; }'
};

有关示例,请参阅 https://www.typescriptlang.org/play?ts=4.1.3#code/C4TwDgpgBAQghgZ2gXigbwFBW1AZge3wC4oFgAnASwDsBzAbixwCM5ySyq7GcpWAvDhRoMMAXwwYAxvmpkocEgAU2wSnAA2AHnhIAfFFSZeBYlADkARgBMAZnMAacY2mz5cAPqhI+XCW8QvgqG6EzYpiRWdo5hfGyRNvZOYi4ycsB8IcY4ERaJMSmSafLMXuCBflABQcxZsblRSbGs7HnRyYxAA

【问题讨论】:

  • Typescript 是 structurally typed 语言。所以,只要a_typeof 包含a 的所有mandaory 元素,它就不会关心它有什么额外的元素。它会认为它是一个有效的typeof a
  • 我编辑了描述。在keyof typeof a 中,我只需要遍历真正编写的属性(此处为foo),而不是在Base 中遍历所有属性。
  • 为什么不能在你的案例中使用第二个例子?
  • 我想使用自动补全,当我写 a 时,这很好用,当我使用 : Base 时。

标签: typescript typescript-typings typescript-generics


【解决方案1】:

让我们从编译器的角度仔细看看你想要做什么:

  1. 你告诉它 aBase 类型,以获得自动完成作为副作用。

  2. 然后你告诉它ba 具有相同的类型,即Base

  3. 但是你试图告诉它b 具有与a 相同的类型。

    a 的类型的值是{ foo: string; },即使 TypeScript 允许您这样做,也意味着foo 是必需的可选的。就类型系统而言,这是无稽之谈。

现在,假设您决心规避上述情况。您可以使用一个通用函数来执行此操作,该函数返回您希望自动完成的值的 约束 版本:

const getA = <K extends Base>(a: K) => a;

const a = getA({ foo: "123" });

const a_typeof: typeof a = {
    foo: '123',
    bar: '123', //Error: 'bar' does not exist in type 'Pick<Base, "foo">'
};

Playground

泛型类型参数确保自动完成,而Pick 实用程序类型过滤返回的类型。虽然你会得到你想要的错误,但没有什么能阻止你将 Base 传递给消除错误的泛型类型参数。


回答问题“是否可以使用typeof 来推断 const 变量的实际类型,而与定义的更广泛类型无关?” - 不,这是不可能的。如果您明确指定了更广泛的类型,则无论分配如何都将使用它。

【讨论】:

  • 我认为“不”实际上是正确的答案。我意识到窄类型是正确的,我只想自动完成以方便地创建该类型。所以我混合了两种不同的东西。将此标记为正确答案!
  • @jhp - 再次查看答案后,我注意到可以使解决方法更方便,从而得到您想要的。但是您仍然必须创建一个在运行时浪费空间的函数,以使事情正常运行。
猜你喜欢
  • 2017-05-16
  • 2017-04-13
  • 1970-01-01
  • 2015-11-06
  • 1970-01-01
  • 1970-01-01
  • 2021-06-24
  • 1970-01-01
  • 2022-12-23
相关资源
最近更新 更多