简体   繁体   中英

set type of a property based on an enum type value

I've a type FieldType which is an enum and FieldTypeToTSType which gets a FieldType as a parameter and converts it to the typescript type.


type FieldType = "string" | "int";

type FieldTypeToTSType<T extends FieldType> = 
    T extends "string" ? string
  : T extends "int" ? number
  : never;

but the problem is using it directly works:

FieldTypeToTSType<"string"> // string
FieldTypeToTSType<"int"> // number

but when I'm using FieldType it always defines it as string

const a: FieldType = "int";

type K = FieldTypeToTSType<typeof a>; // string but it should be number

the context that I'm using it:

type FieldType = "string" | "int";
type FieldDefinition = {
  type: FieldType;
};

type EntityDefinition<T> = {
  [K in keyof T]: FieldDefinition;
};

const makeEntity = <T>(et: { [K in keyof T]: FieldDefinition }) => et;

type FieldTypeToTSType<T extends FieldType> = T extends "string"
  ? string
  : T extends "int"
  ? number
  : never;

type EntityRefrence<T extends EntityDefinition<T>, R extends keyof T = keyof T> = {
  [key in R]: FieldTypeToTSType<T[R]["type"]>;
};

const Vacation = makeEntity({
  days: {
    type: "int",
  },
  name: {
    type: "string"
  }
});

type VacationRef = EntityRefrence<typeof Vacation>;

VacationRef's type should be

type VacationRef = {
    days: number;
    name: string;
}

but it is:

type VacationRef = {
    days: string | number;
    name: string | number;
}

It doesn't work because FieldType of source entity is widened in makeEntity and EntityRefrence . To fix this in EntityRefrence - use specific key instead of union of all possible keys:

type EntityRefrence<T extends EntityDefinition<T>> = {
  [key in keyof T]: FieldTypeToTSType<T[key]["type"]>;
};

In makeEntity - passed parameter should have generic type, so its type properly inferred and not widened:

const makeEntity = <T extends { [K in keyof T]: FieldDefinition }>(et: T) => et;

Playground

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM