型ガード
Type Guardを使用すると、条件ブロック内のオブジェクトの型を制限することができます。

typeof

TypeScriptはJavaScriptのinstanceoftypeof演算子の使用を認識しています。条件付きブロックでこれらを使用すると、TypeScriptはその条件ブロック内で異なる変数の型を理解します。ここでは、TypeScriptが特定の関数がstringに存在せず、おそらくユーザーのタイプミスであったことを指摘する簡単な例を示します:
1
function doSomething(x: number | string) {
2
if (typeof x === 'string') { // Within the block TypeScript knows that `x` must be a string
3
console.log(x.subtr(1)); // Error, 'subtr' does not exist on `string`
4
console.log(x.substr(1)); // OK
5
}
6
x.substr(1); // Error: There is no guarantee that `x` is a `string`
7
}
Copied!

instanceof

次はクラスと instanceofの例です:
1
class Foo {
2
foo = 123;
3
common = '123';
4
}
5
6
class Bar {
7
bar = 123;
8
common = '123';
9
}
10
11
function doStuff(arg: Foo | Bar) {
12
if (arg instanceof Foo) {
13
console.log(arg.foo); // OK
14
console.log(arg.bar); // Error!
15
}
16
if (arg instanceof Bar) {
17
console.log(arg.foo); // Error!
18
console.log(arg.bar); // OK
19
}
20
21
console.log(arg.common); // OK
22
console.log(arg.foo); // Error!
23
console.log(arg.bar); // Error!
24
}
25
26
doStuff(new Foo());
27
doStuff(new Bar());
Copied!
TypeScriptは elseを理解しています。そうすればifの中は、特定の型であり、elseの中はその型でないことが分かります。次に例を示します。
1
class Foo {
2
foo = 123;
3
}
4
5
class Bar {
6
bar = 123;
7
}
8
9
function doStuff(arg: Foo | Bar) {
10
if (arg instanceof Foo) {
11
console.log(arg.foo); // OK
12
console.log(arg.bar); // Error!
13
}
14
else { // MUST BE Bar!
15
console.log(arg.foo); // Error!
16
console.log(arg.bar); // OK
17
}
18
}
19
20
doStuff(new Foo());
21
doStuff(new Bar());
Copied!

in

in演算子は、オブジェクト上のプロパティの存在を安全にチェックし、Type Guardとして使用することができます。例えば。
1
interface A {
2
x: number;
3
}
4
interface B {
5
y: string;
6
}
7
8
function doStuff(q: A | B) {
9
if ('x' in q) {
10
// q: A
11
}
12
else {
13
// q: B
14
}
15
}
Copied!

リテラル型のType Guard

異なるリテラル値を区別するには、=== / == / !== / != が利用できます。
1
type TriState = 'yes' | 'no' | 'unknown';
2
3
function logOutState(state:TriState) {
4
if (state == 'yes') {
5
console.log('User selected yes');
6
} else if (state == 'no') {
7
console.log('User selected no');
8
} else {
9
console.log('User has not made a selection yet');
10
}
11
}
Copied!
ユニオン型の中にリテラル型がある場合にも同じ方法が使えます。次のように共通するプロパティの値をチェックすることで、異なるユニオン型を区別できます。
1
type Foo = {
2
kind: 'foo', // Literal type
3
foo: number
4
}
5
type Bar = {
6
kind: 'bar', // Literal type
7
bar: number
8
}
9
10
function doStuff(arg: Foo | Bar) {
11
if (arg.kind === 'foo') {
12
console.log(arg.foo); // OK
13
console.log(arg.bar); // Error!
14
}
15
else { // MUST BE Bar!
16
console.log(arg.foo); // Error!
17
console.log(arg.bar); // OK
18
}
19
}
Copied!

strictNullChecksを使用したnullとundefinedのチェック

TypeScriptは十分賢いので、次のように== null / != nullチェックをすることでnullundefinedの両方を排除できます。
1
function foo(a?: number | null) {
2
if (a == null) return;
3
4
// a is number now.
5
}
Copied!

ユーザー定義のType Guard

JavaScriptには非常に豊富な実行時の解析サポートが組み込まれていません。単純なJavaScriptオブジェクトだけを使用している場合(構造型を使用する場合)、 instanceofまたはtypeofにアクセスすることさえできません。これらの場合、Type Guard関数をユーザーが定義することができます。これは、someArgumentName is SomeTypeを返す関数です。次に例を示します。
1
/**
2
* Just some interfaces
3
*/
4
interface Foo {
5
foo: number;
6
common: string;
7
}
8
9
interface Bar {
10
bar: number;
11
common: string;
12
}
13
14
/**
15
* User Defined Type Guard!
16
*/
17
function isFoo(arg: any): arg is Foo {
18
return arg.foo !== undefined;
19
}
20
21
/**
22
* Sample usage of the User Defined Type Guard
23
*/
24
function doStuff(arg: Foo | Bar) {
25
if (isFoo(arg)) {
26
console.log(arg.foo); // OK
27
console.log(arg.bar); // Error!
28
}
29
else {
30
console.log(arg.foo); // Error!
31
console.log(arg.bar); // OK
32
}
33
}
34
35
doStuff({ foo: 123, common: '123' });
36
doStuff({ bar: 123, common: '123' });
Copied!

Type Guardsとコールバック

TypeScriptは、コールバック内でタイプガードがアクティブのままであることは危険なため、これを想定していません。例えば、
1
// Example Setup
2
declare var foo:{bar?: {baz: string}};
3
function immediate(callback: ()=>void) {
4
callback();
5
}
6
7
8
// Type Guard
9
if (foo.bar) {
10
console.log(foo.bar.baz); // Okay
11
functionDoingSomeStuff(() => {
12
console.log(foo.bar.baz); // TS error: Object is possibly 'undefined'"
13
});
14
}
Copied!
この修正は、推測された安全な値をローカル変数に格納し、自動的に外部から変更されないようにするのと同じくらい簡単で、TypeScript はそれを簡単に理解することができます。
1
// Type Guard
2
if (foo.bar) {
3
console.log(foo.bar.baz); // Okay
4
const bar = foo.bar;
5
functionDoingSomeStuff(() => {
6
console.log(bar.baz); // Okay
7
});
8
}
Copied!
最終更新 1yr ago