項目46 型が不明な値には、anyではなくunknownを使う
unknown型はanyの型安全な代替手段。値があることを知っているが、その型が何か知らない、気にしない場合に利用する
すべての型はunknown型に代入可能だが、unknown型には代入不可
any型にはすべての型が代入可能
戻り値の型が不明なYAMLパーサー関数を作成する場合
戻り値がany型だとTypeScriptによる型チェックが妨害される
項目43 可能なかぎり狭いスコープでany型を使うのルールにも反する
code:ts
function parseYAML(yaml: string): any {...}
const book = parseYAML(`
name: Jane Eyre
author: Charlotte Brontë
`);
console.log(book.title); // エラーなし、実行時に「undefined」をログに出力する
book('read'); // エラーなし、bookは関数でないため実行時にエラーを投げる
unknown型を使うことで、型安全性が高まる
any型では発生しなかった型チェッカーのエラーが発生するようになる
code:ts
function safeParseYAML(yaml: string): unknown {
return parseYAML(yaml);
}
const book = safeParseYAML(`
name: The Tenant of Wildfell Hall
author: Anne Brontë
`);
console.log(book.title);
// ~~~~ 'book' is of type 'unknown'
// 'book' は 'unknown' 型です
unknown型は、そのままの状態では何もできないので、必然的に型アサーションや型の絞り込みを強制させることができる
code:ts
const book = safeParseYAML(`
name: Villette
author: Charlotte Brontë
`) as Book;
console.log(book.title);
// ~~~~~ Property 'title' does not exist on type 'Book'
function processValue(value: unknown) {
if (value instanceof Date) {
value
// ^? (parameter) value: Date
}
}
unknown型の代わりにジェネリックが使われることがあるが、これはあまり良くない手段
型安全でないため
code:ts
function safeParseYAML<T>(yaml: string): T {
return parseYAML(yaml);
}
unknown型を使って呼び出し元で型アサーションを使ったり、型の絞り込みをしたほうが安全
ジェネリックの不必要な使用については項目51 不必要な型パラメーターを避ける
unknown型は二重アサーションとしてanyの代わりで使える
code:ts
declare const foo: Foo;
let barAny = foo as any as Bar;
let barUnk = foo as unknown as Bar; // こちらの方がまだ、安全っぽい
unknown型の代替手段としてはobjectや{}を使うことで、より狭い型として表現できる
{}型はnullとundefined以外の値からなる
Object 型({})はプリミティブ型の値を代入できる
code:ts
const object: Object = 'test'; // 代入可能
object型はすべての非プリミティブ型の値を代入できる
code:ts
const object: object = 'test'; // 型エラー発生
const object: object = []; // 代入可能
#TypeScript