Можете ли вы применить ключ к объекту, но пусть машинописный текст определяет тип значения? - PullRequest
0 голосов
/ 17 июня 2019

Я пытаюсь создать объект, в котором я хотел бы применить ключи, но с радостью позволю машинописи определять типы значений.Краткий пример:

const fooVals = {
  a: null,
  b: null,
  c: null,
  e: null,
}

type TfooVals = typeof fooVals
type JustKeysOfFooVals = { [key in keyof TfooVals]: any};

// TS deduces correct types of foo1Vals but does not let me know e is missing
const foo1Vals = {
  a: 'string',
  b: 10,
  c: Promise.resolve('string') , 
//  e: () => { console.log('bar') }
}

// lets me know 'e' is missing, but makes types any
const foo2Vals: JustKeysOfFooVals = {
  a: 'string',
  b: 10,
  c: Promise.resolve('string') , 
  e: () => { console.log('bar') }
}

TSPlayground :

Возможно ли это?

1 Ответ

1 голос
/ 17 июня 2019

Я бы порекомендовал использовать универсальную вспомогательную функцию, которая ограничивает свой ввод подтипом из JustKeysOfFooVals и просто возвращает свой ввод без расширения it:

const justKeysOfFooVals = <T extends JustKeysOfFooVals>(t: T)=>t;

Вы бы тогда использовали это так:

const foo1Vals = justKeysOfFooVals({
  a: 'string',
  b: 10,
  c: Promise.resolve('string') , 
//  e: () => { console.log('bar') }
}); // error! property 'e' is missing

const foo2Vals = justKeysOfFooVals({
  a: 'string',
  b: 10,
  c: Promise.resolve('string') , 
  e: () => { console.log('bar') }
}); // okay
foo2Vals.e(); // okay

Вас предупреждают о пропущенных ключах, и он не забывает о типах значений. Надеюсь, это поможет; удачи!

Ссылка на код


Обновление: вспомогательная функция может отключить избыточные проверки свойств . Если они вам нужны (а вам может и не понадобиться, ведь значение {a: "a", b: "b"} является совершенно допустимым экземпляром типа {a: string}), вы можете использовать другое общее ограничение для имитации точных типов :

type Exactly<T, U> = T & Record<Exclude<keyof U, keyof T>, never>;
const justKeysOfFooVals = <T extends Exactly<JustKeysOfFooVals, T>>(t: T)=>t;

const foo3Vals = justKeysOfFooVals({
  a: 'string',
  b: 10,
  c: Promise.resolve('string') , 
  e: () => { console.log('bar') },
  f: 1 // error!
}); // number is not assignable to never

Ссылка на код

Удачи снова!

...