如何强制缩小到打字稿中类型化常量的特定类型?

时间:2021-02-01 12:34:44

标签: typescript typescript-typings typescript-generics

我的问题是是否可以使用 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,我会得到想要的效果。

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 示例。

1 个答案:

答案 0 :(得分:1)

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

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

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

  3. 然后你试着告诉它 b avalue 具有相同的类型。< /p>

    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 变量的实际类型,而与定义的更广泛的类型无关?” - 不,这是不可能的。如果您明确指定了更宽的类型,则无论赋值如何都会使用它。