gpt4 book ai didi

具有特定键和值集的 TypeScript 类型

转载 作者:行者123 更新时间:2023-12-04 03:49:05 25 4
gpt4 key购买 nike

更新版本

完整 Playground 在这里

https://www.typescriptlang.org/play?#code/C4TwDgpgB...

我正在尝试创建一个只允许特定键的对象类型,但对于每个键,您必须将特定的通用类型扩展为值。即

type AllowedKeys = "a" | "b" | "c";

type MyGenericType<T extends AllowedKeys> = {
type: T;
}

type MyObjectTypeGuard = {
[T in AllowedKeys]: MyGenericType<T>
}

// This is what I am aiming at, I tried to make sure that I now have an interface the should prevent me from using the only allowed keys with the allowed values
interface MyObject extends MyObjectTypeGuard {
a: { type: "a" } & { foo: "foo" };
b: { type: "b" } & { bar: "bar" };
c: { type: "c" } & { baz: "baz" };
}

现在这可以防止我使用错误值的键

// I cannot accidentially use the wrong base types
interface MyObject2 extends MyObjectTypeGuard {
a: { type: "b" } & { foo: "foo" };
b: { type: "b" } & { bar: "bar" };
c: { type: "c" } & { baz: "baz" };
}

// Or use completely wrong types even
interface MyObject3 extends MyObjectTypeGuard {
a: { foo: "foo" };
b: { type: "b" } & { bar: "bar" };
c: { type: "c" } & { baz: "baz" };
}

但我仍然可以做其他我希望自己避免的事情

// But I can still miss a key
interface MyObject4 extends MyObjectTypeGuard {
a: { type: "a" } & { foo: "foo" };
b: { type: "b" } & { bar: "bar" };
}

// And I can still add arbitrary stuff
interface MyObject5 extends MyObjectTypeGuard {
a: { type: "a" } & { foo: "foo" };
b: { type: "b" } & { bar: "bar" };
c: { type: "c" } & { baz: "baz" };
fooBar: "baz";
}

我正在寻找一种方法来定义一个对象类型/接口(interface),它强制我使用所有键(并且只使用那些键)并让我为每个值扩展一个特定的通用类型

旧版本

We have a base model BodyNode which can be extended into variants:


type BodyNode<T extends NodeType> = { readonly type: T; };

type NodeWithText<T extends NodeType> = BodyNode<T> & WithText; type
NodeWithChildren<T extends NodeType> = BodyNode<T> & WithChildren;
type NodeWithReference<T extends NodeType> = BodyNode<T> &
WithReference;

interface WithText { readonly text: string; }

interface WithChildren { readonly children: Node[]; }

interface WithReference { readonly href: string; } ```

to be able to iterate over the node types, we created an interface
that maps `NodeType`s to variants

types:

```typescript type BodyNodes = { [T in NodeType]: BodyNode<T>; };

interface Nodes extends BodyNodes { headline: NodeWithText;
paragraph: NodeWithChildren; anchor: NodeWithReference; }

type Node = Nodes[keyof Nodes]; ```

implementation:

```tsx type Components = { [K in BodyNode]: React.FC<{ node:
Nodes[K] }>; };

const components: Components = { headline: Headline, paragraph:
Paragraph, anchor: Anchor, };

const Body = (props: { nodes: Node[] }) => ( <div>
{props.nodes.map(node => {
const Component = components[node.type];
return <Component node={node} />;
})} </div> ); ```

we are using the node types as keys for the `Nodes` as well as the
`Components` and with this we can map the Nodes with the right types
to the right components in type safe way.

But this implementation has a big flaw:

```typescript type BodyNodes = { [T in NodeType]: BodyNode<T>; };

interface Nodes extends BodyNodes { headline: BodyNode<'headline'>;
paragraph: BodyNode<'headline'>; // ^^^^^^^^
this will cause an error, which is what we want anchor:
BodyNode<'anchor'>; yadda: 'foobar'; //^^^^^^^^^^^^^^^^ this is
still possible because we can extend BodyNodes in //
any way and that's not cool } ```

We'd love to find a way to write a type that allows only

- specific keys as above
- for specific keys only specific values as above
- requires each key to be there
- BUT forbids extending, ie. have an exact implementaition of that type and nothing else

最佳答案

我不认为你可以用接口(interface)做到这一点:“扩展”总是意味着你可以扩展。但是下面是什么?它有点笨拙,因为我们在 <> 中定义我们的新类型,但我认为它可以满足您的需求。

type AllowedKeys = "a" | "b" | "c";

type MyGenericType<T extends AllowedKeys> = {
type: T;
}

type MyObjectTypeGuard = { [T in AllowedKeys]: MyGenericType<T> };

type VerifyType<T extends MyObjectTypeGuard &
{ [U in Exclude<keyof T, AllowedKeys>]: never }> = T;

// Incorrect type letters or missing 'type', additional properties,
// and missing properties lead to errors
type VerifiedType = VerifyType<{
a: { type: "a" } & { foo: "foo" };
b: { type: "b" } & { bar: "bar" };
c: { type: "c" } & { baz: "baz" };
}>;

const obj: VerifiedType = {
a: { type: "a", foo: "foo" },
b: { type: "b", bar: "bar" },
c: { type: "c", baz: "baz" }
}

关于具有特定键和值集的 TypeScript 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64705079/

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