Проблема
У вас есть следующие типы:
type OptionalData<T> = T extends undefined ? { data?: any } : { data: T };
export type DataObject<T = any> = {
item?: string | null;
} & OptionalData<T>;
Когда вы вводите переменную как DataObject
с параметром типа, являющимся объединением типа (например, string
) и undefined
вы ожидаете, что свойство данных будет набрано как тип объединения, однако оно набрано как any
:
const data: DataObject<string | undefined> = { data: ... }
// data.data should be typed as `string | undefined` however
// data.data is typed as `any`
Что происходит?
Документация TypeScript для условных типов здесь полезно. Он гласит:
Условные типы, в которых проверяемый тип является параметром голого типа, называются распределительными условными типами. Распределительные условные типы автоматически распределяются по типам объединения во время создания экземпляра. Например, экземпляр T extends U ? X : Y
с аргументом типа A | B | C for T
разрешается как (A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y)
.
- Документация по распределительным условным типам
Итак, в вашем случае он разрешается до
| (string extends undefined ? { data?: any } : { data: T })
| (undefined extends undefined ? { data?: any } : { data: T })
Первое условное выражение разрешается до { data: T }
, а второе разрешается до { data?: any }
. Я считаю, что типы объединения будут разрешаться в тип, который является наиболее общим c, поэтому в конечном итоге тип будет { data?: any }
.
Решение
Здесь OptionalData
обновлено, чтобы он работал должным образом :
type OptionalData<T> = [T] extends [undefined] ? { data?: any } : { data: T };
Мы просто заключили T
и undefined
в квадратные скобки ([]
), превратив их в кортежи (или технически монументальные, потому что у них только один элемент). Вот демонстрация .
Почему это работает?
Давайте еще раз вернемся к документации по условным типам, с некоторым дополнительным акцентом на важных частях:
Условные типы, в которых проверяемым типом является параметр голый тип , называются распределительными условными типами. Распределительные условные типы автоматически распределяются по типам объединения во время создания экземпляра.
Поскольку мы превратили эти голые типы в кортежи, они больше не голые. И поскольку они больше не обнажены, их больше не раздают.