Определение типа для функции, которая добавляет параметры к типу ввода - PullRequest
1 голос
/ 16 апреля 2020

Я хотел бы определить функцию, которая в общем случае может добавить недостающие параметры к типу, например:

interface completeType {
  id: string
  text: string
}

interface otherInterface {
  something: string
  id: string
}

function withDefaultId<T extends {id?: string}>(obj: T): T & {id: string} {
   if(!obj.id) {
      obj.id = "21"
   }
   return obj
}

const completeObject: completeType = withDefaultId({text: "my text"})

Но это дает мне ошибку, что T не присваивается типу вывода. Как мне правильно это сформулировать? (Попытка эмулировать стиль пробот context.repo, который добавляет в определенные поля для вас).

1 Ответ

1 голос
/ 16 апреля 2020

Компилятор не сужает тип необязательного свойства до требуемого при назначении. Это так, как задумано, хотя иногда это расстраивает. См. microsoft / TypeScript # 29827 для некоторого обсуждения. И вообще, записи свойств не сужают тип целого объекта, см. microsoft / TypeScript # 35086 для некоторого обсуждения. Сужение потока управления при назначении происходит только тогда, когда вы присваиваете значение переменной / свойству типа объединения, и это происходит только с конкретной переменной / свойством, которую вы устанавливаете. Все это означает, что obj.id = "21" не изменяет тип obj, как видит компилятор.

Самый простой способ справиться с этим - использовать утверждение типа просто сказать компилятору, что вы уверены, что возвращаете правильный тип. Вы знаете, что сделали обязательным свойство id, поэтому можете просто утверждать, что оно истинно:

function withDefaultId<T extends { id?: string }>(obj: T): T & { id: string } {
    if (!obj.id) {
        obj.id = "21"
    }
    return obj as T & { id: string };
}

Менее просто изменить вашу реализацию на форму, которую компилятор уже видит как возвращающую правильный тип , Например, что-то вроде:

function withDefaultId<T extends { id?: string }>(obj: T): T & { id: string } {
    return Object.assign(obj, { id: obj.id || "21" });
}

Это должно дать вам аналогичный результат (при условии, что obj не имеет некоторого динамического c setter для свойства id, или есть какие-то другие волшебные c странности. Но теперь нет ошибки компилятора.


Хорошо, надеюсь, это поможет; удачи!

Ссылка на игровую площадку с кодом

...