У меня есть интерфейс, определенный как
interface IExample {
property1: string;
property2: number;
property3?: number;
property4?: string;
}
Как заставить все необязательные свойства принимать значение null? Я не хочу добавлять null
к каждому дополнительному свойству.
Я пытался создать этот тип, но это не работает
type SetOptionalKeysNullable<T> = {
[K in keyof T]: T[K] extends undefined ? undefined | null : T[K];
};
Для обнаружения необязательных свойств требуется нечто большее, чем просто проверка undefined
. См. ссылку на эту игровую площадку. Соответствует ли это вашим потребностям? Если да, то я напишу ответ или найду подходящий дубликат. Если нет, то что мне не хватает?
@jcalz Спасибо, это то, чего я в идеале хотел. Работает так, как ожидалось. Просто интересно, можем ли мы сделать его рекурсивным, чтобы вложенные поля вели себя одинаково.
Вы можете обратиться к исходному коду Partial
:
type Partial<T> = {
[P in keyof T]?: T[P];
};
Определите свой собственный интерфейс PartialMayBeNull
:
type PartialMayBeNull<T> = {
[P in keyof T]: T[P] | null
}
Использование:
const example: PartialMayBeNull<IExample> = {
property1: null,
property2: null,
}
Если вы хотите сделать свойство необязательным и иметь значение null, измените приведенную выше реализацию:
type PartialMayBeNull<T> = {
[P in keyof T]?: T[P] | null
}
Извините, я упустил из виду, что это повлияет на обязательные свойства, измените их следующим образом.
interface IExample {
property1: string
property2: number
property3?: number
property4?: string
}
type IsPartialProperty<K extends keyof T, T> = undefined extends T[K] ? K : never
type IsRequiredProperty<K extends keyof T, T> = undefined extends T[K] ? never : K
type PartialProperties<T> = {
[K in keyof T as IsPartialProperty<K, T>]: T[K] | null
}
type RequiredProperties<T> = {
[K in keyof T as IsRequiredProperty<K, T>]: T[K]
}
type PartialMayBeNull<T> = PartialProperties<T> & RequiredProperties<T>
const example: PartialMayBeNull<IExample> = {
property1: 'foo',
property2: null, // Error: Type null is not assignable to type number
property3: null, // No error
}
Это также влияет на необязательные свойства.
Это сделает все свойства обнуляемыми, а не только необязательные.
Ответ был изменен со ссылкой на другой вопрос
В {x: string | undefined}
свойство x
не является необязательным, но этот код будет рассматривать его как таковое.
type SetOptionalKeysNullable<T> = {
[K in keyof T]: T[K] extends NonNullable<T[K]>
? T[K]
: T[K] | null | undefined;
};
Это то, что сработало для меня
Для чего это нужно {a: string | null, b: number | undefined}
? Ни одно из этих свойств не является необязательным, но ваш код добавит undefined
к первому и null
ко второму.
Лучший способ обнаружить необязательные свойства — использовать (небезопасную, но удобную) возможность назначения отсутствующего свойства дополнительному свойству отсутствующему свойству. То есть {}
можно присвоить {a?: string}
, но не {a: string}
или {a: string | undefined}
. Любая проверка, которая просто смотрит на undefined
, в конечном итоге не сможет отличить необязательные свойства от обязательных свойств, ожидающих undefined
. Итак, для каждого свойства K
в keyof T
, если {}
присваивается Pick<T, K>, то K
необязательно в T
:
type SetOptionalKeysNullable<T> = {
[K in keyof T]: T[K] | ({} extends Pick<T, K> ? null : never)
};
Давайте проверим это:
interface IExample {
property1: string;
property2: number;
property3?: number;
property4?: string;
}
type ExOut = SetOptionalKeysNullable<IExample>;
/* type ExOut = {
property1: string;
property2: number;
property3?: number | null | undefined;
property4?: string | null | undefined;
} */
// none of these properties are optional
type Also = SetOptionalKeysNullable<{
a: string;
b: string | null;
c: string | undefined;
}>
type AlsoOut = SetOptionalKeysNullable<Also>;
/* type AlsoOut = {
a: string;
b: string | null;
c: string | undefined;
} */
Выглядит хорошо. Все необязательные свойства null
добавляются в их домен, тогда как ни с одним из обязательных свойств ничего не происходит.
Видели это? stackoverflow.com/questions/68713907/…