【问题标题】:User defined type guard on outer type / nested property?外部类型/嵌套属性上的用户定义类型保护?
【发布时间】:2020-12-18 04:02:05
【问题描述】:

我有一个与user defined type guards 相关的问题,特别是是否可以实现一个谓词函数作为子字段的类型保护。

考虑以下示例:

type ContentFoo = {
  kind: "foo";
  foo: string;
}

type ContentBar = {
  kind: "bar";
  bar: string;
}

type Content = ContentFoo | ContentBar;

直接在 content: Content 上定义类型保护就可以了,例如:

function isFooContent(content: Content): content is ContentFoo {
  return content.kind === "foo";
}

现在想象Content 被包装成另一种类型,例如:

type Entry = {
  id: string;
  content: Content;
}

我想要实现的是基于 Entry 包装类型定义类型保护。我天真的猜测是:

function isFooEntry(entry: Entry): entry.content is ContentFoo {
  return entry.content.kind === "foo";
}

但是编译器不喜欢这种谓词函数的语法:

Cannot find namespace 'entry'.

有没有其他方法可以编写一个“向上一级”操作的谓词函数?还是因为 TypeScript 编译器无法通过外部类型跟踪类型,所以这样的谓词函数在设计上是不可能的?


预期用途是:

if (isFooEntry(entry)) {
  console.log("It must have a foo", entry.content.foo)
}

不用写

if (isFooContent(entry.content)) {
  console.log("It must have a foo", entry.content.foo)
}

【问题讨论】:

  • 你能提供更多关于你如何使用这个函数的信息吗? isFooEntry(),我的意思是?

标签: typescript


【解决方案1】:

这样的事情应该可以解决问题。 Playground

function isFooEntry(entry: Entry): entry is Omit<Entry, 'content'> & { content: ContentFoo } {
  return entry.content.kind === "foo";
}

【讨论】:

  • 非常感谢!现在我可以解析它了:Omit&lt;Entry, 'content'&gt; 首先从Entry 类型中“删除”该属性,然后&amp; { content: ContentFoo } 将它带回来,但现在在显式ContentFoo 类型下。有道理。
  • @bluenote10 您可以将Omit&lt;Entry, 'content'&gt; &amp; { content: ContentFoo } 提取为EntryFoo 类型以简化签名。
猜你喜欢
  • 2019-01-03
  • 2015-12-19
  • 2021-10-31
  • 1970-01-01
  • 1970-01-01
  • 2020-11-11
  • 2018-03-26
  • 2016-09-06
  • 2020-02-01
相关资源
最近更新 更多