TypeScript:用于A类型的索引键和用于B类型的保留键

时间:2019-06-08 14:19:11

标签: javascript typescript

我需要定义一个类型,该类型允许将预定义键分配为类型A,并将所有其他键分配为类型B

我尝试了以下操作,但出现以下错误:

type Foo = "foo";
type Bar = "bar";

interface Fuz {
  [key: string]: Foo
}

interface Qux {
  display?: Bar
}

type Bash = Qux & Fuz;

// ERROR: TS2322 -- Type '"bar"' is not assignable to '"foo"'
const a: Bash = {
  display: "bar"
};

// ERROR: TS2322 -- Type '"foo"' is not assignable to '"bar"'
const b: Bash = {
  display: "foo"
};

我想这基本上与写作相同:

interface Fuz {
  // ERROR: TS2411 -- property 'display' of type '"bar"' is not assignable to string index type '"foo"'
  display?: Bar
  [key: string]: Foo
}

有没有办法实现上述目标?

2 个答案:

答案 0 :(得分:1)

考虑this case

interface Fuz {
    // pretend this was valid for a moment
    display: 'bar';
    [k: string]: 'foo';
}


declare let x: Fuz; // lets say we have a variable of type Fuz


let index = 'display' // index is right now type string
let value = x[index]; // x[string] === 'foo' so `typeof value === 'foo'`
let value2 = x['display']; // x['display'] === 'bar' so `typeof value2 === 'bar'`

console.assert(value === value2);
// ERROR: This condition will always return 'false' since the types '"foo"' and '"bar"' have no overlap.
// which is obviously not correct, they are derived from the same property!

从定义中可以看出,您提出的value显然包含字符串bar,但据打字稿所理解,它实际上是foo

据我所知,没有一种方法可以提供“未明确定义的键”字段,以使x[string]是所有适用字符串的并集。

我知道要获得所需行为的唯一方法是指定值是Foo或在字符串键bar的情况下是Bar,因此字符串索引必须为联合:

interface CorrectFuz {
    bar: 'bar';
    [k: string]: 'bar' | 'foo';
}

对此可能有更好的解决方案,我需要有关您实际用例的更多信息以了解如何提供帮助。

答案 1 :(得分:0)

  

我需要定义一个类型,该类型允许将预定义键分配给类型A,并将所有其他键分配给类型B

我认为您对Typescript的期望是错误的。类型不会被“分配”给任何东西。创建类型联合时,您将通过松开类型的定义来扩展该变量的可能值,而在创建类型交集时,您将通过扩展类型的定义来限制该变量的可能值。