Open3

TypeScriptで型を良い感じに処理

yutake27yutake27

Record<string, string>のkeyとvalueを逆転させて、型も保持する

const invertDict = <T extends Record<string, string>>(dict: T) =>
  Object.keys(dict).reduce((obj, key) => {
    obj[dict[key as keyof T]] = key;
    return obj;
  }, {} as Record<string, string>) as { [k in keyof T as T[k]]: k };
const original = { key1: "value1", key2: "value2" } as const;

// type {
//    readonly value1: "key1";
//    readonly value2: "key2";
//}
const inverted = invertDict(original);

になる

yutake27yutake27

objectの指定した一部のプロパティだけRequiredにする

// TがUnionでも対応できるようにunion distributionを起こしている
type RequiredByKeys<T, K extends keyof T = keyof T> = T extends T
  ? Required<Pick<T, K>> & Omit<T, K>
  : never;

メインは Required<Pick<T, K>> & Omit<T, K>だけど、
Tがunionの場合は使えないのでT extends T ?でunion distributionを起こしている

yutake27yutake27

Object.keysでkeyの方を維持

// 普通のObject.keysだと
const hoge = {
  a: 0,
  b: 1,
  c: 2,
} as const

const keys = Object.keys(hoge) // type string[]
// stringにcastされてしまう
// 方を維持できるやつ定義
const ObjectKeys = Object.keys as <T>(o: T) => (keyof T)[];
const keys = ObjectKeys(hoge) // type ('a' | 'b' | 'c')[]