#javascript #node.js #typescript #typescript-generics
Вопрос:
interface UserFlags {
isDev: boolean;
isAdmin: boolean;
isMod: boolean;
}
const flagPositions: FlagPositions<UserFlags> = {
isDev: 0,
isAdmin: 1,
isMod: 2,
};
Как бы вы реализовали FlagPositions
, чтобы для интерфейса с типом требовался 1 универсальный параметр { [name: string]: boolean }
и чтобы все свойства интерфейса присутствовали в новом интерфейсе, но имели тип number
?
Я пробовал использовать различные методы keyof
, но ни один из них не сработал.
Редактировать: Я получил эту работу после публикации, но я бы хотел, чтобы это был интерфейс
type FlagPositions<F> = {
[K in keyof Required<F>]: number;
};
Ответ №1:
Вы хотите FlagPositions<T>
быть сопоставленным типом, ключи которого совпадают, keyof T
но значения которого number
совпадают . Вы можете написать это вот так:
type FlagPositions<T> = { [K in keyof T]: number };
И убедитесь, что он работает так, как вы хотите:
const flagPositions: FlagPositions<UserFlags> = {
isDev: 0,
isAdmin: 1,
isMod: 2,
};
Обратите внимание , что нет необходимости ограничиваться T
{[name: string]: boolean}
или Record<keyof T, boolean>
, но вы можете сделать это, если хотите:
type FlagPositions<T extends Record<keyof T, boolean>> =
{ [K in keyof T]: number };
declare const oops: FlagPositions<{ a: number }>; // error!
// ----------------------------> ~~~~~~~~~~~~~
// Types of property 'a' are incompatible.
Вы не можете сделать FlagPositions<T>
interface
это, потому что интерфейсы должны иметь ключи, известные во время компиляции, и T
являются универсальными и могут иметь все виды ключей. Но как только у вас будет FlagPositions<UserFlags>
тип, который имеет известные ключи (это isDev
, isAdmin
, и isMod
), вы можете interface
расширить это:
interface UserFlagPositions extends FlagPositions<UserFlags> { }
const u: UserFlagPositions = {
isDev: 2,
isAdmin: 1,
isMod: 0
}
Комментарии:
1. Большое спасибо. Можно ли преобразовать его в интерфейс?
2. Ты можешь писать
interface UserFlagPositions extends FlagPositions<UserFlags> {}
. Но вы меняете область вопроса, и любое дальнейшее изменение области, вероятно, требует отдельного сообщения3. Извините, я не совсем ясно выразился. Интерфейс был тем, что я изначально хотел, однако, поскольку он работает, все в порядке