TypeScript не может сузить тип

(Если вы найдете имя получше, дайте мне знать)

У меня есть функция, которая получает два аргумента: задание и сотрудник. Сотрудник не является обязательным: если работа запланирована, сотрудник будет там, в противном случае он не нужен.

type Job = {
    name: string;
    schedule?: string;
}

type WorkingEmployee = {
    doWork: (jobName: string) => void
}

function f(job: Job, employee?: WorkingEmployee){
    if (job.schedule) {
        if (employee) {
            employe.do(job.name)
        }
    }
}

Однако я знаю больше. Я знаю, что если работа запланирована, то сотрудник будет. Итак, я хочу добиться этого и воспользоваться этими знаниями:

type ScheduledJob = {
    task: string;
    isDoable: string;
}
type Employee<T> = T extends ScheduledJob ? WorkingEmployee : undefined;

function f<T extends Job>(job: T, employee: Employee<T>){
    if (job.schedule) {
        employee.doWork(job.name);
    }
}

Но машинописный текст не принимает: "Object is possibly undefined", имея в виду employee.doWork. Почему не принимает? Если schedule там, то мы точно знаем, что employee не undefined.

Мои вопросы: 1. Почему компилятор не принимает этот код? 2. Есть ли способ достичь того, что я пытаюсь сделать здесь?


person enanone    schedule 09.04.2020    source источник


Ответы (1)


Универсальные типы сужаются при вызове функции. На момент определения вы знаете только, что T это что-то вроде Job. Typeguard сузит тип job, но не изменит то, к чему относится T.

 let a: T, b: T;

 if(a.narrow) {
   // a can be narrowed down, but it is unknown wether the same applies to b. Thus T cannot be narrowed.
 }

Однако вы можете перегрузить f (не уверен, работает ли это так, как задумано, но это понятнее, чем общая функция с условными типами):

 function f(job: ScheduledJob, employee: WorkingEmployee);
 function f(job: Job, employee?: WorkingEmployee) {
   //...
 }
person Jonas Wilms    schedule 09.04.2020