#typescript
Вопрос:
Существует пользовательский тип Options
(вложенный объект) , который я создал. Я хочу использовать этот тип DefaultProperties
для создания объекта, содержащего свойства по умолчанию.
type Options = {
id: number,
text: string | undefined,
properties: {
title: string,
subtitle: string | undefined,
}
}
type DefaultProperties = Pick<Options, "properties">;
Конечно, свойства по умолчанию не могут быть undefined
такими . Поэтому я хочу исключить undefined
из своих типов союзов.
Для этой цели должны быть встроенные функции, такие как NonNullable<T>
или Exclude<T,UnionType>
.
Я попробовал три разных способа удаления undefined
, но ни одно решение не работает с моим типом.
type Options = {
id: number,
text: string | undefined,
properties: {
title: string,
subtitle: string | undefined,
}
}
type DefaultProperties = Pick<Options, "properties">;
// Try #1: does not work
type Type1 = NonNullable<DefaultProperties>;
// Try #2: does not work
type NotOptional<Type> = {
[Property in keyof Type]-?: Type[Property];
};
type Type2 = NotOptional<DefaultProperties>;
// Try #3: does not work
type Type3 = Exclude<Options, undefined>;
Пример: Игровая площадка для машинописи
Как я могу удалить все undefined
s из всех типов объединения типов?
Правка: Все undefined
буквы s должны быть удалены из моего типа. Например:
Options['text'] : string
(Больше нетundefined
)Options['properties']['subtitle'] : string
(Больше нетundefined
)
Позже я хочу использовать тип для этого (например):
const options : Options = { ... };
const defaults: DefaultProperties= { ... }; // With no undefined
const node : HTMLElement = .... ;
node.innerHTML = options.properties.subtitle !== undefined ? options.properties.subtitle : defaults.properties.subtitle;
Когда defaults.properties.subtitle
имеет тип string | undefined
, компилятор выдает ошибку, потому innerHTML
что только позволяет strings
. За это я хочу исключить undefined
.
Комментарии:
1.
type NonNullable<T> = T extends undefined ? never: T;
2. Компилятор все еще говорит , что
DefaultProperties['properties']['subtitle']
у него есть типstring | undefined
, но я хочу, чтобы он был из типаstring
.3. Попробуй
text?: string
4. Ключ не должен быть необязательным.
Ответ №1:
Вы действительно близки к своему NotOptional
типу утилиты , и Exclude
проблема в том, что вы определяете DefaultProperties
как объект со properties
свойством , но пытаетесь удалить undefined
его из DefaultProperties
, а не из его properties
свойства.
В комментарии вы сказали, что хотите DefaultProperties
быть в той же форме, properties
что и на Options
. Это означает, что его основная форма (до того, как мы попытаемся удалить undefined
) такова Options["properties"]
. Так что:
type NotOptional<Type> = {
[Property in keyof Type]: Exclude<Type[Property], undefined>;
};
type DefaultProperties = NotOptional<Options["properties"]>;
Тесты:
const defaults1: DefaultProperties = {
title: "foo",
subtitle: undefined, // <== Error as desired
};
const defaults2: DefaultProperties = {
title: "foo",
subtitle: "something", // <== No error
};
Вы также можете рассмотреть возможность устранения необязательности (объединение двух вещей, которые вы пробовали).:
type NotOptional<Type> = {
[Property in keyof Type]-?: Exclude<Type[Property], undefined>;
};
type DefaultProperties = NotOptional<Options["properties"]>;
Тесты:
const defaults1: DefaultProperties = {
title: "foo",
subtitle: undefined, // <== Error as desired (wrong type for `subtitle`)
};
const defaults2: DefaultProperties = { // <== Error as desired (missing `somethingElse`)
title: "foo",
subtitle: "something",
};
const defaults3: DefaultProperties = { // <== No error
title: "foo",
subtitle: "something", // <== No error
somethingElse: "x",
};
Комментарии:
1. Я хочу, чтобы
DefaultOptions
она имела ту же форму,Options[properties]
что и . При использованииpick
properties
также добавляется ключ. Не знаю, как его удалить, но решение с ключомproperties
работает для меня. @основная проблема: В обоих случаях компилятор возвращаетstring | undefined
ключsubtitle
. Этоundefined
то, что я хочу исключить. Например, используя его позже:document.querySelector('#n')!.innerHTML = options.properties.subtitle !== undefined : options.properties.subtitle : defaultOptions.properties.subtitle
. Когда defaultOptions.properties.subtitle являетсяstring | undefined
ошибкой.2. @MichaelT — Извините, я уже два или три раза перепутал этот ответ. Я считаю, что текущая версия на самом деле делает то, что вы описали (что, кстати, не было неясно, я просто неправильно протестировал первую версию, а затем допустил ряд ошибок редактирования во второй версии).