🔤

TypeScriptの型定義で正規表現っぽいかんじでstring型を詳しく定義する

2022/11/07に公開

TypeScriptで変数の型としてstring型を使っているとき、もっと細かく定義ことを知ったので紹介しておきます。

簡単に例を示すと以下のようなコードを書くことができます。

type MarkerTime =`${number| ''}${number}:${number}${number}`;

let a: MarkerTime = "0-00";  // この代入はエラーになる
let b: MarkerTime = "0:00";  // この代入はOK
let c: MarkerTime = "09:00"; // この代入はOK

TypeScript: TS Playgroundでこのコードを書くと、エラー箇所がすぐにわかります。

上の例では、テンプレートリテラルを使ってMarkerTimeという型を作成しています。
テンプレートリテラルの中ではプレースホルダ(${})でnumber型と空文字列を使い、
時刻を示す文字列(9:00とか18:00)だけを許可する型を作成できました。

ちょっと応用した使い方

上の例を使ってちょっと応用します。
ちょっと面倒なエラーが発生する型定義(下例だとDateMappingError)を回避し、
エラーが発生せず、少し細かく型定義ができている型を使っています(下例だとDateMappingGood)。

type Year = `${number}${number}${number}${number}`;
type Month = `${number | ''}${number}`;
type Day = `${number | ''}${number}`;

interface DateMappingError { // エラーになる
	[key: string]: {  // 2重にネストした型定義
		[key: string]: {
			[key: string]: string
		}
	}
	otherInfo: {
        // このotherInfoプロパティがエラーになる 
        // エラー内容: Property 'otherInfo' of type '{ [key: string]: string; }' is not assignable to 'string' index type '{ [key: string]: { [key: string]: string; }; }'.(2411)
        // 「otherInfo」は文字列なので上で定義した2重にネストした型定義に対して判定がおこなわれてしまうが、
        // このotherInfoは1回しかネストしておらず、型不一致と判断される
		[key: string]: string
	}
}

interface DateMappingGood {
	[key: Year]: {
		[key: Month]: {
			[key: Day]: number
		}
	},
	otherInfo: {
		[key: string]: string
	}
}

const map1: DateMappingGood = {
    '2022': {
        '1': {
            '1': 123,
            '2': 225,
        },
        '10': {
            '20': 31,
        }
    },
    otherInfo: {
        key1: 'value1',
        key2: 'value2',
    }
};

参考

GitHubで編集を提案

Discussion