【问题标题】:Can you enforce a key on an object but let typescript deduce the type of Value?您可以在对象上强制执行键,但让打字稿推断值的类型吗?
【发布时间】:2019-10-31 08:54:02
【问题描述】:

我正在尝试创建一个我想强制执行键的对象,但很高兴让打字稿推断出值的类型。 一个简单的例子是

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

这可能吗?

【问题讨论】:

  • 未知类型在这里可能很方便
  • 使所有类型未知。

标签: typescript typescript3.0


【解决方案1】:

我建议使用通用辅助函数,它将其输入限制为JustKeysOfFooVals子类型,并且只返回其输入而不加宽它:

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

您会收到有关缺少键的警告,并且不会忘记值类型。希望有帮助;祝你好运!

Link to code


更新:辅助函数可能会禁用excess property checks。如果您需要这些(并且您可能不需要,毕竟值{a: "a", b: "b"}{a: string} 类型的完全有效实例),那么您可以使用另一个通用约束来模拟exact types

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

Link to code

再次祝你好运!

【讨论】:

  • 是的,这似乎是唯一的方法,尽管应该有另一种方法。将打开一个问题
猜你喜欢
  • 2020-04-09
  • 1970-01-01
  • 2020-05-31
  • 2021-06-08
  • 2018-09-19
  • 1970-01-01
  • 2015-11-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多