Вы можете mimi c с типами объединения.
Простой пример:
interface INonNullable {
id: string;
type: string;
}
interface INullable {
id?: undefined;
type?: undefined;
}
type FinalType = INonNullable | INullable;
function testId(x: FinalType)
{
if (x.id !== undefined) {
x.type // string
}
}
FinalType
необязательно, вы можете просто использовать (x: INonNullable | INullable)
везде.
Добавить функцию защиты типа:
Вы также можете создать функцию с защитой типа для проверки ваших критериев и сужения типа таким образом:
interface INonNullable {
id: string;
type: string;
}
interface INullable {
id?: undefined;
type?: undefined;
}
type FinalType = INonNullable | INullable;
function isNonNullable(x: FinalType): x is INonNullable
{
return x.id !== undefined;
}
let x = {};
if (isNonNullable(x)) {
x.type // string;
}
У вас есть больше информации об этом в документации Typescript: Определяемые пользователем охранники типов
Многоразовые Empty<T>
:
Еще один изящный вариант, как упоминалось в комментарии Патрика Робертса, для создания более многократно используемого решения с использованием сопоставленных типов и обобщений:
interface INonNullable {
id: string;
type: string;
}
type Empty<T> = {
[K in keyof T]?: undefined;
}
type FinalType<T> = T | Empty<T>;
function testId(x: FinalType<INonNullable>) {
if (x.id !== undefined) {
x.type // string
}
}