Typescript:如何在没有运行时工件的情况下生成编译时集的通用版本?

Typescript:如何在没有运行时工件的情况下生成编译时集的通用版本?,typescript,Typescript,我试图让Typescript警告我我们使用的API不正确(我希望看到的错误已标记): 这是可行的,但是太冗长了——泛型的用处有点失去了。除此之外,随着列表的大小和复杂性的增加,这变得越来越难维护,并且很难说服此API的消费者以这种方式键入他们的内容 如果没有运行时工件和上述冗长的内容,我如何实现相同级别的类型安全性?好的,让我们来清理一下。你的泛型比必要的要宽一点;大多数情况下,您使用的是完整的对象类型,而实际上只关心它们的键名。这是我的零钱: // Icon is the same inter

我试图让Typescript警告我我们使用的API不正确(我希望看到的错误已标记):

这是可行的,但是太冗长了——泛型的用处有点失去了。除此之外,随着列表的大小和复杂性的增加,这变得越来越难维护,并且很难说服此API的消费者以这种方式键入他们的内容


如果没有运行时工件和上述冗长的内容,我如何实现相同级别的类型安全性?

好的,让我们来清理一下。你的泛型比必要的要宽一点;大多数情况下,您使用的是完整的对象类型,而实际上只关心它们的键名。这是我的零钱:

// Icon is the same
interface Icon { src: string; }

// you just need key names here (K), not a full object type (T)
type IconRegistry<K extends string> = Record<K, Icon>

// you don't really need IconSet, but for convenience, here it is
type IconSet = IconRegistry<string>

// the old P and S didn't do anything except determine keys
// let's just use those keys (K) directly
type UiBuilder = <K extends string>(iconRegistry: IconRegistry<K>) => {
  withIcon(iconName: K): null,
};
您需要将有效的
IconSet
作为参数传递给
VerifyIconRegistry
。让我们看看它与无效的
列表图标的作用:

const listIcons = {
  sort: { src: 'sort.svg' },
  email: { source: 'email.svg' } 
};

declare var witness: 
  VerifyIconRegistry<typeof listIcons> // ERROR
  // Property 'src' is missing in type '{ source: string; }'
const profileIcons = {
  security: { src: 'security.svg' },
  email: { src: 'email.svg' }
};

declare var witness:
  VerifyIconRegistry<typeof profileIcons> // OKAY
那一个起作用了(我们重新使用了
witness
名称)

最后,让我们确保没有破坏
buildUi()


看起来不错。希望有帮助;祝你好运

我不知道为什么这里需要泛型。因此,如果删除T、S并将它们固定到各自的类型名,那么在最后一步可以很容易地消除冗长。如果我从
IconRegistry
中删除类型
T
,那么它将与
IconSet
相同,不是吗?如果是这样的话,
buildUi
函数就不会像预期的那样出错。你可以通过发布到TS PlayGround来确认哦,明白了。感谢您的解释。我想,标识函数不能由typescript内联。。
type VerifyIconRegistry<T extends IconSet> = any
const listIcons = {
  sort: { src: 'sort.svg' },
  email: { source: 'email.svg' } 
};

declare var witness: 
  VerifyIconRegistry<typeof listIcons> // ERROR
  // Property 'src' is missing in type '{ source: string; }'
const profileIcons = {
  security: { src: 'security.svg' },
  email: { src: 'email.svg' }
};

declare var witness:
  VerifyIconRegistry<typeof profileIcons> // OKAY
function buildUi(builder: UiBuilder) {
  builder(profileIcons).withIcon('security'); // OKAY
  builder(profileIcons).withIcon('bold'); // ERROR
  // Argument of type '"bold"' is not assignable 
  // to parameter of type '"security" | "email"'.
}