为所有具有方法的键创建一个类型?

问题描述 投票:0回答:1

我有一个具有以下结构的对象:

const items = {
    a: { create: () => "hello" },
    b: { create: () => "hello", delete: () => "goodbye" },
    c: { delete: () => "goodbye" },
}

我想为

items
的所有键创建类型,这些键具有不同的方法。所以:

type CreateItems = 'a' | 'b'
type DeleteItems = 'b' | 'c'

如何从

CreateItems
对象生成
DeleteItems
items
,而不是对类型进行硬编码?

typescript
1个回答
0
投票

这是如何做到这一点的示例(游乐场链接):

const items = {
  a: { create: () => "hello" },
  b: { create: () => "hello", delete: () => "goodbye" },
  c: { delete: () => "goodbye" },
};

type MyType<T, Name extends string> = {
  [key in keyof T]: T[key] extends { [key in Name]: () => string } ? key : never;
}[keyof T];

type CreateItems = MyType<typeof items, "create">; // "a" | "b"
type DeleteItems = MyType<typeof items, "delete">; // "c" | "d"

为了解释,让我们一次看一下:

type MyType<T, Name extends string> = 

这正在创建一个泛型类型。泛型有两个参数可以控制它:

T
是我们要查看的对象,以及
Name
是我们关心的属性名称。

{
  [key in keyof T]: // ...
}

这部分正在制作映射类型

items
有一个
a
b
c
,并且该对象也将具有这三个。

T[key] extends { [key in Name]: () => string } ? key : never;

这个条件将检查该对象是否具有我们正在寻找的属性。例如,如果

Name
create
,那么该对象必须看起来像
{ create: () => string }
,或者从其扩展的东西(即,允许额外的属性)。如果匹配,我们将值设置为等于键,否则我们将值设置为 never。

结合到目前为止的步骤将生成一个如下所示的类型(如果 Name == “create”):

{
  a: "a",
  b: "b",
  c: never
}

还有最后一篇:

[keyof T]

这将使我们刚刚创建的对象类型中存在的所有值进行并集。这是“a”、“b”和

never
,但永远不会被忽略。

© www.soinside.com 2019 - 2024. All rights reserved.