Я бы порекомендовал использовать универсальную вспомогательную функцию, которая ограничивает свой ввод подтипом из 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
Ссылка на код
Удачи снова!