我如何组合一个“不是”不同类型的类型?

时间:2021-05-12 15:04:40

标签: typescript

对不起,如果这些都没有意义,但我对如何在此处进行打字感到非常困惑。

我有一些这样的接口:

interface AAA { a: string; }
interface BBB { b: string; }
interface CCC { c: string; }
interface DDD { d: string; }

这是我的“NOT”类型用例:

// I'm not even sure if this is a correct or useful type...
type SomeType<T> = T extends { a: string } ? AAA 
                   : T extends { b: string } ? BBB
                   : T extends { c: string } ? CCC
                   : DDD;

class AlphabetNode<T> {
  // How do I specify "NOT<T>" in typescript? I tried using "Exclude<any, T>" but it
  // doesn't prevent "T" objects from being pushed into the array.
  public children: SomeType<NOT<T>>[] = [];

  constructor(public data: SomeType<T>) {}
}

// I would prefer to not have to specify the type "AAA" if there exists a solution.
const x: AlphabetNode<AAA> = new AlphabetNode({ a: 'I like the letter A' });

// Valid
x.children.push({ b: 'This should be valid' });
x.children.push({ c: 'This should also be valid' });

// Both of these statements should be invalid, but as my types are currently set up, 
// typescript is fine with both.
x.children.push({ b: 'Uh', c: 'Oh' });
x.children.push({ a: 'Why is this valid?' });

1 个答案:

答案 0 :(得分:0)

好的,我一直在玩这个,我找到了一个我现在必须使用的部分解决方案......

interface AAA { a: string }
interface BBB { b: string }
interface CCC { c: string }
interface DDD { d: string }

type WhichAlphabet<T> = T extends AAA ? AAA 
                      : T extends BBB ? BBB 
                      : T extends CCC ? CCC 
                      : T extends DDD ? DDD : never;

class AlphabetNode<T> {
  public children: Exclude<WhichAlphabet<any>, T>[] = [];

  constructor(public data: WhichAlphabet<T>) {}
}

const a = new AlphabetNode<AAA>({ a: 'Letter a' });
a.children.push({ b: 'Letter b' }); // Ok
a.children.push({ c: 'Letter c' }); // Ok
a.children.push({ d: 'Letter d' }); // Ok
a.children.push({ x: 'Letter x' }); // invalid
a.children.push({ a: 'Another letter a' }); // invalid

所以这一切都很好,但唯一的问题是......

a.children.push({ b: 'Another letter b', c: 'Another letter c' }); // Ok

在这一点上,我只需要坚持下去,因为我已经浪费了太多时间。也许这会帮助某人想出“真实”的答案。