Почему распространение не работает с пересекающимся типом c? - PullRequest
2 голосов
/ 01 мая 2020

Я пытаюсь обернуть функцию, которая принимает аргумент определенного типа c, чтобы создать функцию, которая принимает аргумент немного другого типа. Вот код, слегка упрощенный:

type DifferentArgs<T> = {
    myNewArg: number;
} & T;


function f<T, U>({ myNewArg, ...t }: DifferentArgs<T>, g: (q: T) => U) {
    return g(t);
}

Это кажется мне логичным: t обязательно будет присвоено T.

Компилятор не согласен:

 'Pick<DifferentArgs<T>, Exclude<keyof T, "myNewArg">>' is 
  assignable to the constraint of type 'T', but 'T' could 
  be instantiated with a different subtype of constraint '{}'

Может кто-нибудь объяснить как может быть другой T и как я могу это исправить?

1 Ответ

1 голос
/ 01 мая 2020

Ух, это заняло у меня много времени.

Вот проблема. Представьте, что код выше скомпилирован . Далее представьте, что вы пытаетесь вызвать f() следующим образом:

type KillerType = {
  myNewArg(): void;
}

f( k, (kt: KillerType) => kt.myNewArgs());

Теперь нет значения, которое вы можете использовать для k, что имеет смысл. Оно должно иметь свойство myNewArg быть как числом, так и функцией со значением void, что совершенно невозможно. Даже игнорируя проблему проверки типов, f() будет вызывать анонимную функцию без какого-либо значения myNewArg.

Это можно исправить:

type DifferentArgs<T> = {
    myNewArg: number;
} & T; 

type SameArgs<T> = Omit<T, 'myNewArg'>;

function f<T, U>({ myNewArg, ...t }: DifferentArgs<T>,
                 g: (q: SameArgs<T>) => U): U {
    return g(t);
}

По сути, вы должны пообещайте компилятору, что параметру g никогда не понадобится свойство с именем myNewArg, поэтому конфликт никогда не может возникнуть .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...