お知らせ
現在サイトのリニューアル作業中のため、全体的にページの表示が乱れています。
TypeScriptをぼちぼちやってきた中で、型推論が素直に決まらないみたいな所が出てきたので書き置きとして残しておきます
具体的には何かしらの関数を通して処理を隠蔽すると上手くいかなくなるケースがあります
検査関数的なものを通した場合に、後続処理で期待通り型が推論されなくなるケースです
type HogePiyo = 'hoge' | 'piyo';
type InputProps<ValueT> = {
value: ValueT;
error: string;
};
const required = (val: string) => {
return val === '';
};
const registerHogePiyo = (value: HogePiyo) => {
console.log('register', value);
};
const input: InputProps<HogePiyo | ''> = {
value: '',
error: '',
};
if (required(input.value)) {
input.error = 'ERR';
console.error(input.error);
} else {
// ここでは input.value は 'hoge' | 'piyo' となるはずだが
// TSC は 'hoge' | 'piyo' | '' と解釈する
registerHogePiyo(input.value);
}
type HogePiyo = 'hoge' | 'piyo';
type InputProps<ValueT> = {
value: ValueT;
error: string;
hasError: boolean;
};
const required = <ValueT>(obj: InputProps<ValueT | ''>) => {
if (obj.value === '') {
return { value: '', error: '必須入力です', hasError: true };
} else {
return { value: obj.value, error: '', hasError: false };
}
};
const registerHogePiyo = (value: HogePiyo) => {
console.log('register', value);
};
const input: InputProps<HogePiyo | ''> = {
value: '',
error: '',
hasError: false,
};
const result = required(input);
if (result.hasError) {
console.error(result.error);
} else {
// ここでは input.value は 'hoge' | 'piyo' となるはずだが
// TSC は 'hoge' | 'piyo' | '' と解釈する
registerHogePiyo(result.value);
}
export {};
オブジェクトに型判定用のプロパティを生やしas
で型を明示することでクリアしています
type HogePiyo = 'hoge' | 'piyo';
type InputProps<ValueT> = {
value: ValueT;
error: string;
hasError: boolean;
};
const required = <ValueT>(obj: InputProps<ValueT | ''>) => {
if (obj.value === '') {
return { value: '', error: '必須入力です', hasError: true } as {
value: '';
error: string;
hasError: true;
};
} else {
return { value: obj.value, error: '', hasError: false } as {
value: ValueT;
error: string;
hasError: false;
};
}
};
const registerHogePiyo = (value: HogePiyo) => {
console.log('register', value);
};
const input: InputProps<HogePiyo | ''> = {
value: '',
error: '',
hasError: false,
};
const result = required(input);
if (result.hasError) {
console.error(input.error);
} else {
registerHogePiyo(result.value);
}
export {};
throw
を書く必要性があり、バンドル後に残っている以上、このthrow
をcatch
する必要性がある
as
に限りなく近く、ぶっちゃけas
で書いたほうが楽as
を使わず現実的な工数で開発するというのは、割と非現実ではないかという感触があります