Skip to content

Instantly share code, notes, and snippets.

@todays-mitsui
Created September 1, 2022 05:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save todays-mitsui/e89635fea70bbf2f879e15ae88ba1b0d to your computer and use it in GitHub Desktop.
Save todays-mitsui/e89635fea70bbf2f879e15ae88ba1b0d to your computer and use it in GitHub Desktop.
schema から型定義を作る
// 文字列リテラル型を対応するプリミティブ型に変換する
type Lift<T> = T extends readonly [ string, ...string[] ] ? LiftTuple<T>
: T extends 'null' ? null
: T extends 'boolean' ? boolean
: T extends 'object' ? { [ key: string ]: any }
: T extends 'array' ? any[]
: T extends 'string' ? string
: T extends 'number' | 'integer' ? number
: any;
// 上記の変換のタプル版、空タプルは受け付けない
type LiftTuple<T> = T extends readonly [ infer Head, ...infer Tail ]
? Tail extends [ string, ...string[] ]
? Lift<Head> | LiftTuple<Tail>
: Lift<Head>
: never;
// ↓↓↓ 使ってみる
type T1 = Lift<'string'>;
// ^ = string
type T2 = Lift<'integer'>;
// ^ = number
type T3 = Lift<readonly [ 'string', 'integer', 'null' ]>;
// ^ string | number | null
// ========================================================================== //
// schema から型定義を作る
type InferSchema<T extends { [key: string]: { type: string | readonly string[] } }>
= { [K in keyof T]: Lift<T[K]['type']> }
// ↓↓↓ 使ってみる
const attributes = {
foo: { type: 'string', default: '' },
bar: { type: 'integer' },
buz: { type: 'boolean' },
qux: { type: [ 'string', 'null' ] }
} as const;
type Attributes = InferSchema<typeof attributes>;
// ^ = {
// readonly foo: string;
// readonly bar: number;
// readonly buz: boolean;
// readonly qux: string | null;
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment