首页 > 解决方案 > 如果块范围类型不通过泛型反映

问题描述

class Foo {
  asdf: string;
}

class Bar {
  qwerty: number;
}

export type EntityTypeName = 'Foo' | 'Bar';

export type EntityType = Foo | Bar;

export type EntityTypeByName<N> =
  N extends 'Foo' ? Foo :
  N extends 'Bar' ? Bar :
  any;

class Wrapper <N extends EntityTypeName = EntityTypeName, T extends EntityType = EntityTypeByName<N>> {
  entityTypeName: N;
  entity: T;
}

const wrapper1 = new Wrapper<'Foo'>();

  wrapper1.entityTypeName; // "Foo"
  wrapper1.entity; // Foo

const wrapper2 = new Wrapper();

if (wrapper2.entityTypeName === 'Foo') {
  wrapper2.entityTypeName; // "Foo"
  wrapper2.entity; // Foo | Bar (expect Foo)
}

见:https ://stackblitz.com/edit/typescript-sqd5uf

我希望第 39 行会Foo在鼠标悬停时显示类型,因为它位于从第 37 行开始的 if 块中,并且因为T第 25 行的泛型在第 20 行被EntityTypeByName<N>定义。有没有办法完成第 39 行显示类型Foo

标签: typescript

解决方案


你想要的行为是不正确的。既然wrapper2是 a Wrapper<"Foo" | "Bar", Foo | Bar>,那么 to be 是有效的wrapper2.entityTypeName"Foo"wrapper2.entityto be a是有效的Bar。要捕获 和 之间的关系entityTypeNameentity您需要使用可区分的联合类型:

type Wrapper<N extends EntityTypeName = EntityTypeName> =
  {[P in N]: {entityTypeName: P, entity: EntityTypeByName<P>}}[N];

let wrapper1: Wrapper<'Foo'>;

  wrapper1.entityTypeName; // "Foo"
  wrapper1.entity; // Foo

let wrapper2: Wrapper;

if (wrapper2.entityTypeName === 'Foo') {
  wrapper2.entityTypeName; // "Foo"
  wrapper2.entity; // Foo
}

推荐阅读