将不正确的变量类型传递给函数不会发出类型错误

时间:2019-12-01 10:17:08

标签: typescript

您能解释为什么我将错误的变量类型传递给函数ts时不会发出类型错误吗?

export class CreateCategoryDto implements Omit<Category, 'id' | 'children' | 'parent'> {
  name: string;

  parentId: number;
}

export async function createCategory(dto: CreateCategoryDto) {
  return getRepository(Category).save(dto);
}

const data = { id: 555, name: 'sdfsdf', parentId: 55 };
ctx.body = {
    data1: await createCategory(data), // not emit
    data: await createCategory({ id: 555, name: 'sdfsdf', parentId: 55 }), // emit that params must be without id
  };

2 个答案:

答案 0 :(得分:2)

这与excess property checkingobject literal freshness有关。

您可能会问什么时候认为对象文字是新鲜的?

当Typescript为您推断其类型并且既没有类型断言也没有将对象常量分配给变量时,该对象常量将被认为是新鲜的。

// using type assertion, this works
data: await createCategory({ id: 555, name: 'sdfsdf', parentId: 55 } as CreateCategoryDto)

在第一种情况下,您将其分配给变量,因此新鲜度消失了,并且没有多余的属性检查。

const data = { id: 555, name: 'sdfsdf', parentId: 55 }; // you assigned it to a variable

data1: await createCategory(data)

但是,在第二种情况下,您将对象常量直接传递给函数,而没有先将其分配给变量,因此Typescript推断了其类型:对象常量是新鲜的。

data: await createCategory({ id: 555, name: 'sdfsdf', parentId: 55 }) // this object is fresh

在这种情况下,我们称之为多余的属性检查,其工作原理如下:当您尝试将新鲜的对象文字类型T分配给另一个类型U且T具有不在U中的属性时,Typescript抱怨。这对于检测拼写错误很有用。

从文档中引用:

  

[...] TypeScript认为此代码中可能存在错误。当将它们分配给其他变量将它们作为参数传递时,对对象文字进行特殊处理并进行多余的属性检查。如果对象文字具有“目标类型”所没有的任何属性,则会出现错误[...]

这也会产生错误:

var categoryDto: CreateCategoryDto = { id: 555, name: 'sdfsdf', parentId: 55 }

而事实并非如此:

var categoryDto = { id: 555, name: 'sdfsdf', parentId: 55 }
var test: CreateCategoryDto = categoryDto

对象类型在其成员中是协变的(您需要T或T的子类型),多余的属性无关紧要。这可能会导致不安全的行为,但是作者希望在易用性和安全性之间取得平衡。这里,由于对象文字是新鲜的,因此涉及过多的属性检查。

答案 1 :(得分:0)

DTO的形状表示应该有两个字段

名称:字符串 ParentId:数字

此属性名称和属性数据类型的约定由传递给调用方法的两个对象文字参数满足。

请注意,我没有使用过打字稿,这个答案是根据我在使用C#之类的静态/强类型语言和Javascript之类的动态/弱类型语言的经验得出的。