如何从类型中忽略属性?

时间:2019-04-16 08:47:07

标签: typescript types

我对打字稿中的省略类型有疑问,所以我知道省略类型与Pick相对,其构建方式如下:

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>

但是我不知道如何构造一个Omit类型。我有一个Student的界面,看起来像这样:

interface Student { 
name: string, 
surname: string, 
age: number, 
email: string 
}

我需要一个函数,该函数将Student作为具有某些给定属性的输入,并输出被忽略的Student。该函数应如下所示:

let omit_student = <K extends keyof Student>(student: Student, ...props: K[] ): Omit<Student, K> => null!

但是我不知道如何动态地省略Student的给定属性以及该函数的主体中应该发生什么。

这样调用函数:omit_student(student1, "name", "age") 应该输出以下类型:

{ 
surname: string, 
email: string 
}

2 个答案:

答案 0 :(得分:0)

要声明Omit类型,请使用CRice的答案:

interface Student { 
    name: string, 
    surname: string, 
    age: number, 
    email: string 
}

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>

let student: Student = { name: "John", surname: "Doe", age: 21, email: "John.Doe@test.com" }
let omit_student: Omit<Student, "name" | "age"> = student

这将创建仅包含surnameemail的新类型。但是,这只会在编译时抱怨(使用surnameemail以外的其他属性时),您必须自己编写一个过滤器方法以符合用Omit描述的接口。 / p>

function omitStudent(student: Student, ...args: string[]): Omit<Student, "name" | "age"> {
    for (let key of args) {
        delete student[key]
    }
    return student
}

console.log(student);
console.log(omitStudent(student, "name", "age"));

尽管我意识到这可能不像您在问题中所问的那样“动态”。

答案 1 :(得分:0)

常见的混淆原因是TypeScript中的对象类型不是exact。众所周知,类型为Student的值具有适当类型的namesurnameageemail属性,但不知道只有 这些属性。这样,您可以通过向它们添加已知的属性来extend种类型:

interface Student { 
    name: string, 
    surname: string, 
    age: number, 
    email: string 
}

interface HogwartsStudent extends Student {
    house: string,
    spells: string[]
}

在上面,HogwartsStudentStudent的特殊类型。如果我给您Student,您可能不知道她不是HogwartsStudent,所以您无法确定她没有housespells属性。

Omit<T, K>类型的别名产生T超类型。也就是说,T扩展了Omit<T, K>。类型T的每个值也是类型Omit<T, K>的值。您仅使用Omit<T, K>来“忽略”的是K中带有键的属性的已知存在和类型。


您要的不仅是从类型中删除已知键,而且要从生成的对象中删除实际属性。这需要在运行时以与JavaScript中完全相同的方式发生:

function omit_student<K extends Array<keyof Student>>(
  student: Student, ...props: K): Omit<Student, K[number]> {
    const newStudent: Omit<Student, K[number]> = Object.assign({}, student);
    for (let prop of props) {
        delete (newStudent as any)[prop];
    }
    return newStudent;
}

请注意,我为K参数使用了rest tuple type,但是您也可以按照自己的方式进行操作。

希望有帮助。祝你好运!