2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

string型だけど補完も効かせたい

Last updated at Posted at 2024-05-28

背景

関数で文字列以外も受け入れたいけど、特定の文字列も補完を効かせたいとき

Union型

const unionInput = (input: "hoge" | "fuga") => {
  return input;
};

VSCode上でちゃんと補完されます。

スクリーンショット 2024-05-28 11.31.02.png

動的な値を代入だとうまくいかない

例えばAPIから返ってくる値は、string型になってしまうときが多いと思います。

const unionInput = (input: "hoge" | "fuga") => {
  return input;
};

const resFromApi = { name: "hoge", age: 20 };

unionInput(resFromApi.name); // 型エラー

スクリーンショット 2024-05-28 11.34.33.png

nameの値はhogeですが、string型になってしまうので、エラーを起こしてます。

Union に string 追加

const unionOrStringInput = (input: "hoge" | "fuga" | string) => {
  return input;
};

unionOrStringInput("fuga");
unionOrStringInput("test"); // 範囲の広い string が優先されるので, hoge, fugaは補完されない

範囲の広いstringに引っ張られ、補完が効かない

スクリーンショット 2024-05-28 11.47.10.png

動機

関数を使う時は、補完を効かせたい
だけど、stringも受け入れたい

結論: Omitを使ってできました

追記: string & {} もできます(@sugoroku_y さんありがとうございます)

Omit

const unionOrStringOmitInput = (input: "hoge" | "fuga" | Omit<string, "hoge" | "fuga">) => {
  return input;
};

ちゃんと補完も効いていいかんじです。
スクリーンショット 2024-05-28 11.39.25.png

string & {}

@sugoroku_y さんより

const unionOrStringOmitInput = (input: "hoge" | "fuga" | string & {}) => {
  return input;
};

スクリーンショット 2024-05-30 9.29.26.png

ちゃんと補完効いています。
@sugoroku_y さん、ありがとうございます。

ジェネリックにしてみた

上記のunionOrStringOmitInput を汎用的に使えるように、ジェネリックで型を作ってみました。

// ジェネリックを使ってみたパターン

type StringOr<T extends string> = Input | Omit<string, T>;
type HogeOrFuga = "hoge" | "fuga";

const stringOrInput = (input: StringOr<HogeOrFuga>) => {
  return input;
};

stringOrInput("fuga");
stringOrInput("test");

zodでやってみた

import { z } from "zod";

const HogeOrFugaSchema = z.enum(["hoge", "fuga"]);
type HogeOrFuga = z.infer<typeof HogeOrFugaSchema>;

const unionOrStringInput = (input: HogeOrFuga | Omit<string, HogeOrFuga>) => {
  const parsed = HogeOrFugaSchema.safeParse(input);
  return parsed.success ? parsed.data : "failed";
};

const resFromApi = { name: "hoge", age: 20 };

unionOrStringInput(resFromApi.name);

補完効いていいかんじです。

スクリーンショット 2024-05-28 12.07.16.png

参考

2
0
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?