Я сталкиваюсь с проблемой, пытающейся заставить машинопись распознавать ключи объекта javascript для меня, в то же время применяя тип значения каждого ключа, потому что я хочу создать тип ключей объекта, поэтому я не могу просто создать обычный type MyObject = { [key: string]: <insert type> }
.
Представьте себе объект myobject
, где я извлекаю его ключи, например:
const myobject = {
foo: {},
bar: {}
};
type MyObjectKeys = keyof typeof myobject; // 'foo' | 'bar'
Как я могу добавить определения типов к значениям ключей, сохраняя при этом возможность извлекать / наследовать определения ключей? Если я сделаю что-то подобное, я больше не смогу извлечь точные ключи объекта, а только тип (строка):
type MyObject = { [key: string]: { value: boolean }}
const myobject = {
foo: { value: true },
bar: { value: false }
};
type MyObjectKeys = keyof typeof myobject; // string
Я подумал, что смогу добиться этого, создав Вспомогательная функция, например:
function enforceObjectType<T extends MyObject>(o: T) {
return Object.freeze(o);
}
const myobject = enforceObjectType({
foo: {},
bar: {}
});
Но я бы предпочел определить для нее чистый тип, не загрязняя код, а писать функции, относящиеся только к типам. Есть ли способ разрешить набор строк в качестве ключей типа без повторений?
Цель этого состоит в том, чтобы получить TypeScript, помогающий указывать правильные ключи объекта, такие как (реальное использование немного сложнее , поэтому я надеюсь, что это достаточно хорошо описывает это):
type MyObjectKeys = keyof typeof myobject; // string
function getMyObjectValue(key: MyObjectKeys) {
const objectValue = myobject[key];
}
// suggest all available keys, while showing an error for unknown keys
getMyObjectValue('foo'); // success
getMyObjectValue('bar'); // success
getMyObjectValue('unknown'); // failure
Заключение: Я хочу определить объект как const (фактически с Object.freeze
) и иметь возможность:
- Извлечение точных ключей объекта (без необходимости определения каждого ключа).
- Определение типа каждого ключа без перезаписи ключи к
string
вместо того, что они есть - как 'foo' | 'bar'
.
Полный пример
type GameObj = { skillLevel: EnumOfSkillLevels }; // ADD to each key.
const GAMES_OBJECT = Object.freeze({
wow: { skillLevel: 'average' },
csgo: { skillLevel 'good' }
)};
type GamesObjectKeys = keyof typeof GAMES_OBJECT;
function getSkillLevel(key: GamesObjectKeys) {
return GAMES_OBJECT[key]
}
getSkillLevel('wow') // Get the actual wow object
getSkillLevel('unknown') // Get an error because the object does not contain this.
В соответствии с вышеизложенным, я не могу сделать следующее, потому что перезапишет известные ключи для любой строки:
type GameObj = { [key: string]: skillLevel: EnumOfSkillLevels };
const GAMES_OBJECT: GameObj = Object.freeze({
wow: { skillLevel: 'average' },
csgo: { skillLevel 'good' }
)};
type GamesObjectKeys = keyof typeof GAMES_OBJECT;
function getSkillLevel(key: GamesObjectKeys) {
return GAMES_OBJECT[key]
}
getSkillLevel('wow') // Does return wow object, but gives me no real-time TS help
getSkillLevel('unknown') // Does not give me a TS error
Другой пример: посмотрите, например, this gist и скопируйте его в машинописный текст детская площадка если вы хотите изменить код