[TypeScript] as const のリテラル型比較で出る "重複なし" エラー(TS2367)の直し方
Tech設定値を as const でまとめていたら、IDE に次のエラーが出ました。
This comparison appears to be unintentional because the types
'"ca-pub-1234567890123456"' and '"ca-pub-0000000000000000"' have no overlap. (2367)
何が起きているか
as const を付けると、オブジェクトの各プロパティは値そのものがリテラル型になります。
const ADSENSE = {
client: 'ca-pub-1234567890123456',
} as const;
// ADSENSE.client の型は string ではなく "ca-pub-1234567890123456"
この状態で、別のリテラル文字列と比較すると——
// ❌ TS2367: 型 '"ca-pub-1234567890123456"' と '"ca-pub-0000000000000000"' は重複しない
const enabled = ADSENSE.client !== 'ca-pub-0000000000000000';
ADSENSE.client の型は "ca-pub-1234567890123456" という1つの値しか取らない型なので、"ca-pub-0000000000000000" とは型レベルで絶対に一致しません。TypeScript は「この比較は常に true で無意味では?」と教えてくれているわけです。
これはバグというより、プレースホルダーを実値に置き換えた瞬間に顕在化するタイプの警告です(プレースホルダー時代は両方が同じ型だったので出なかった)。
直し方:比較対象の型を広げる
意図としては「実値かプレースホルダーか」を実行時に判定したいので、片方を string として扱えば、型が重なり比較が許されます。
// ✅ string にキャストして比較
const enabled = (ADSENSE.client as string) !== 'ca-pub-0000000000000000';
他の手段
ケースに応じてこんな選択肢もあります。
-
そのプロパティだけ型注釈で string にする(リテラル型にしたくない場合)
const ADSENSE = { client: 'ca-pub-1234567890123456' as string, } as const; -
そもそも
as constを外す(リテラル型の恩恵が要らないなら)
リテラル型を保ちたい・でもこの比較だけ通したい、というときは比較箇所での as string が一番ピンポイントで済みました。
まとめ
as constはプロパティをリテラル型にする- 別リテラルとの
===/!==は「重複なし」で TS2367 になる - 実行時判定が目的なら、比較側を
as stringで広げる
TypeScript