Home > Blockchain >  Restrict generic typescript type to single string literal value, disallowing unions
Restrict generic typescript type to single string literal value, disallowing unions

Time:07-09

I have a generic entity type, with the generic used to define a field type based on a set of string literals:

type EntityTypes = 'foo' | 'bar' | 'baz';

type EntityMappings = {
  foo: string;
  bar: number;
  baz: Array<string>;
}

type GenericEntity<T extends EntityTypes> = {
  type: T;
  fieldProperty: EntityMappings[T];
}

What I'm trying to do is require all instances of GenericEntity to have a single type field (a string literal) that then defines the type of fieldProperty, e.g:

const instance: GenericEntity<'foo'> = {
  type: 'foo',
  fieldProperty: 'hello',
};

const otherInstance: GenericEntity<'baz'> = {
  type: 'baz',
  fieldProperty: ['a', 'b', 'c'],
}

However, because T extends EntityTypes allows for a union of multiple string literal values in EntityTypes, I'm able to do this, which I want to disallow:

const badInstance: GenericEntity<'foo' | 'baz'> = {
  type: 'baz',
  fieldProperty: 'blah',
};

This compiles because now type is of type 'foo' | 'baz' and fieldProperty is of type string | Array<string>, but the two fields no longer correspond like I intend them to.

Is there a way to restrict the generic declaration on GenericEntity further, to only allow a single unique string literal value? Barring that, is there some other way to insist that any instance of GenericEntity has a type field and a fieldProperty field that correspond?

CodePudding user response:

There is currently no direct way to restrict a generic type parameter to a single member of a union. There's an open feature request at microsoft/TypeScript#27808 to support something like T extends oneof EntityTyes, but that's not implemented yet. If you want to see it happen you might visit that issue and give it a

  • Related