typescript 如何修复对嵌套对象不起作用的类型收缩?

icomxhvb  于 2023-01-18  发布在  TypeScript
关注(0)|答案(3)|浏览(101)

在下面的代码片段中,getChildEmail的倒数第二行没有显示错误,因为child.email不再是string|undefined,而是string,这仅仅是因为收缩。但是,类型错误显示在getChildEmail的最后一行。这是意外的,因为child的类型现在应该满足getEmail的参数的类型。

type Parent = {
  name: string;
  email?: string;
  child: {
    name: string;
    email?: string;
  };
};

function getEmail({ name, email }: { name: string; email: string }) {
  return email;
}

function getChildEmail({ name, email, child }: Parent) {
  child.email.toLocaleLowerCase(); // error as expected, child.email is possibly undefined
  child.email && child.email.toLowerCase(); // working as expected, child.email is a string because of narrowing
  child.email && getEmail(child); // unexpected error as narrowing should make child satisfies the arguments of getEmail function
}

为什么会这样呢?删除最后一个线型错误的最佳实践是什么?
您也可以在下面的 typescript 练习场中查看它

pxiryf3j

pxiryf3j1#

一种选择是使用类型Assert将子级的类型强制转换为正确的类型

child.email && getEmail(child as Required<Parent['child']>);

如果我们也定义一个Child类型,看起来会更简洁一些

type Child = {
    name: string;
    email?: string;
}
type Parent = {
  name: string;
  email?: string;
  child: Child;
};

function getEmail({ name, email }: { name: string; email: string }) {
  return email;
}

function getChildEmail({ name, email, child }: Parent) {
  child.email?.toLocaleLowerCase();
  child.email && child.email.toLowerCase();
  child.email && getEmail(child as Required<Child>);
}

Playground

kse8i1jr

kse8i1jr2#

解决这个问题的一个方法是添加一个类型保护(更多关于类型保护的信息,请参见这里)。

function hasEmail(person: { name: string; email?: string }): person is {name: string; email: string} {
  return person.email !== undefined;
}

然后按以下方式检查:

hasEmail(child) && getEmail(child);

请在此处查看完整的修复代码。

j13ufse2

j13ufse23#

type Parent = {
  name: string;
  email?: string;
  child: {
    name: string;
    email?: string;
  };
};

function getEmail({ name, email }: any ) {
  return email;
}

function getChildEmail({ name, email, child }: Parent) {
  child?.email?.toLocaleLowerCase();
  child.email && child.email.toLowerCase();
  child.email && getEmail(child);
}

检查getEmail()函数的返回类型。2我想,它会导致一个错误。3据我所知,你只想返回email属性,而不是子对象

相关问题