typescript 如何从类型中省略属性?

tcomlyy6  于 2023-04-07  发布在  TypeScript
关注(0)|答案(2)|浏览(155)

我有一个关于Typescript中的Omit类型的问题,所以我知道Omit类型与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 
}

我需要一个函数,它将一个学生作为输入,并具有一些给定的属性,然后输出省略的学生。该函数应该如下所示:
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 
}
fhity93d

fhity93d1#

TypeScript中的对象类型不 * 精确 * 是一个常见的混淆源类型Student的值 * 已知 * 具有适当类型的namesurnameageemail属性,但是不知道是否只有这些属性。这允许你通过添加已知属性来扩展类型:

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元组类型,但您也可以按照自己的方式来做。

vsdwdz23

vsdwdz232#

要声明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描述的接口。

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"));

虽然我意识到这可能不像你在问题中问的那样“动态”。

相关问题