TypeScriptで自作している便利型Tips

公開:2020/10/27
更新:2020/10/27
2 min読了の目安(約2400字TECH技術記事

たまになんかこういうの取り出したいんだけど、なんかないかなーみたいなことになっていくつか作ってみたりしているので、せっかくなので記載しておく🙆🏻♂️ ‍
命名が微妙なので、命名をどうにかしたいというのがある

valueOf<T>

keyOfの反対。
与えられたオブジェクトのvalueのユニオン型を作る

type valueOf<T> = T[keyof T];
const HOGE = {
  hoge: 'test',
  fuga: 'test2'
} as const;

type Hoge = valueOf<typeOf HOGE> // 'test' | 'test2'

mappedConst<T extends string>

与えられた文字列のkeyとvalueを持つオブジェクト

type mappedConst<T extends string>  ={
  [key in T]: key;
};
type HogeOrFuga = 'hoge' | 'fuga';

type HogeFuga = mappedConst<HogeOrFuga>;
/**
{
  hoge: 'hoge',
  fuga: 'fuga'
}
*/

OptionalExceptFor<T, K extends keyof T>

Tの型からKを除いたものをOptionalにする

export type OptionalExceptFor<T, K extends keyof T> = Pick<T, K> &
  Partial<Omit<T, K>>;
type A = {
  foo: string;
  bar: string;
  baz: string;
};

type B = OptionalExceptFor<A, 'foo' | 'bar'>;

const b: B = {
  foo: 'test',
  bar: 'test'
};

RequiredExceptFor<T, K extends keyof T>

Tの型からKを除いたものをRequiredにする

export type RequiredExceptFor<T, K extends keyof T> = Pick<T, K> &
  Required<Omit<T, K>>;
type A = {
  foo: string;
  bar: string;
  baz: string;
};

type B = RequiredExceptFor<A, 'foo' | 'bar'>;

const b: B = {
  baz: 'test'
};

ArgType<T, N>

引数のN番目の型がほしいとき。Nは省略可能で省略された場合は0番目の型

type ArgType<
  T extends (...args: any[]) => any,
  N extends number = 0
> = Parameters<T>[N];
const getNString = (num: number, str: string = 'hoge') => str.padStart(num, str);

type Arg1 = ArgType<typeof getNString>; // number
type Arg2 = ArgType<typeof getNString, 1>; // string

ToKeyValueTuple<T>

keyvalueのタプル型を得たい👀
例えば、関数で

const [state, setState] = useState({});
const updateValue = (key, value) => {
  setState(state => ({
    ...state,
    [key]: value
  }));
};

みたいなときに、stateのkeyValueのペアを引数でもらうのに型をつけたいみたいなモチベーション

type ToKeyValueTupleWithKey<
  T,
  K extends keyof T
> = K extends keyof T ? [K, Pick<T, K>[K]] : never;

type ToKeyValueTuple<T> = ToKeyValueTupleWithKey<T, keyof T>;
const a = {
  a: 'a',
  b: 10,
} as const;
type A = ToKeyValueTuple<typeof a>;

const aa: A = ['a', 10]; // 型 '["a", 10]' を型 '["a", "a"] | ["b", 10]' に割り当てることはできません。

なお、以下だとうまく行かない

type ToKeyValueTupleWithKey<
  T,
  K extends keyof T
> = [K, T[K]];

const aa: A = ['a', 10]; // ['a' | 'b', 'a' | 10]なのでエラーにならない

また気が向いたら追加していきます💪