Uteslut egenskaper av vissa typer i TypeScript


Jag arbetar på ett enkelt projekt för skolan. Och jag undrar om det är möjligt att utelämna alla egenskaper av en viss typ i TypeScript.

type Student = {
    firstName: string
    lastName: string
    age: number
    gender: Gender
    courses: List<Course>
}

Så i det här fallet vill jag bara ha en typ med allt från Student utan "courses".

Är det möjligt att generera en Typ som är Student men utan alla egenskaper som har List-typ? Det måste vara generiskt så att det fungerar på alla typer, till exempel:

type Program = {
    name: string
    errors: List<Error>
    successes: List<Success>
    warnings: List<Warning>
}

Nu skulle det ge en typ som bara innehåller { name: string }

Vet någon hur man gör detta, om det ens är möjligt? Kanske med villkorliga typer? Uteslut om List?

All hjälp uppskattas mycket!

Uppdatering: lägg till kodexempel:

type WithoutList<T> = {
    [K in keyof T]: T[K] extends List<any> ? never : T[K]
}

const select = <a, b extends keyof WithoutList<a>>(arg: a, ...keys: b[]) => {
    return null!
}

const s1: Student = {
    firstName: 's',
    lastName: 's',
    age: 22,
    gender: 'female',
    courses: List<Course>(),
}

select(s1, 'courses') // courses should not be available here!

Svar #1

Du kan använda ommappning av nycklar i mappade typer för att mappa alla nycklar du vill undertrycka till never:

type WithoutList<T> = {
  [K in keyof T as T[K] extends List<any> ? never : K]: T[K]
};

Du kan verifiera att detta fungerar för typerna Student och Program från ditt exempel:

type StudentWithoutList = WithoutList<Student>;
/* type StudentWithoutList = {
    firstName: string;
    lastName: string;
    age: number;
    gender: Gender;
} */

type ProgramWithoutList = WithoutList<Program>;
/* type ProgramWithoutList = {
    name: string;
} */

samt önskat beteende för din select()-funktion:

declare const s1: Student;
select(s1, "age"); // okay
select(s1, 'courses') // error!

Playground-länk till kod

Svar #2

En mappad typ kombinerad med en villkorlig typ som utvärderas till never när typen utvidgar List kommer att ge dig det du vill ha.

Eftersom Gender, List och Course inte är definierade i din kod, kommer jag att använda Array och primitiva typer istället för illustration:

type Student = {
    firstName: string
    lastName: string
    age: number
    courses: Array<string>
}

type WithoutList<T> = {
    [K in keyof T]: T[K] extends Array<any> ? never : T[K]
}

type StudentWithoutCourse = WithoutList<Student>;

Demo