TypeScript 4.0で実現!Promise型のアンラップ
TypeScriptにおけるPromise型のアンラップ
thenメソッドを使う
最も一般的な方法は、then
メソッドを使う方法です。
const promise: Promise<string> = new Promise((resolve) => {
resolve('Hello, world!');
});
promise.then((value) => {
// valueはstring型であることが保証される
console.log(value); // "Hello, world!"が出力される
});
この方法はシンプルで分かりやすいですが、ネストが深くなると可読性が悪くなる可能性があります。
async/awaitを使う
非同期処理をより直感的に記述できるasync
/await
を使う方法もあります。
async function getData(): Promise<string> {
return new Promise((resolve) => {
resolve('Hello, world!');
});
}
async function main() {
const data = await getData();
// dataはstring型であることが保証される
console.log(data); // "Hello, world!"が出力される
}
main();
この方法は可読性が高いですが、すべての状況で使用できるわけではありません。
Promise.prototype.thenを使う
Promise.prototype.then
プロパティを使って、then
メソッドを直接呼び出す方法もあります。
const promise: Promise<string> = new Promise((resolve) => {
resolve('Hello, world!');
});
Promise.prototype.then.call(promise, (value) => {
// valueはstring型であることが保証される
console.log(value); // "Hello, world!"が出力される
});
この方法はあまり一般的ではありませんが、より柔軟な記述が可能です。
型ガードを使う
TypeScript 4.0以降では、型ガードを使ってPromise型のアンラップを行うことができます。
const promise: Promise<string | number> = new Promise((resolve) => {
if (Math.random() > 0.5) {
resolve('Hello, world!');
} else {
resolve(42);
}
});
const value = await promise;
if (typeof value === 'string') {
// valueはstring型であることが保証される
console.log(value); // "Hello, world!"が出力される
} else {
// valueはnumber型であることが保証される
console.log(value); // 42が出力される
}
この方法は、型安全かつ柔軟な記述が可能です。
const promise: Promise<string> = new Promise((resolve) => {
resolve('Hello, world!');
});
promise.then((value) => {
// valueはstring型であることが保証される
console.log(value); // "Hello, world!"が出力される
});
async function getData(): Promise<string> {
return new Promise((resolve) => {
resolve('Hello, world!');
});
}
async function main() {
const data = await getData();
// dataはstring型であることが保証される
console.log(data); // "Hello, world!"が出力される
}
main();
const promise: Promise<string> = new Promise((resolve) => {
resolve('Hello, world!');
});
Promise.prototype.then.call(promise, (value) => {
// valueはstring型であることが保証される
console.log(value); // "Hello, world!"が出力される
});
const promise: Promise<string | number> = new Promise((resolve) => {
if (Math.random() > 0.5) {
resolve('Hello, world!');
} else {
resolve(42);
}
});
const value = await promise;
if (typeof value === 'string') {
// valueはstring型であることが保証される
console.log(value); // "Hello, world!"が出力される
} else {
// valueはnumber型であることが保証される
console.log(value); // 42が出力される
}
実行方法
tsc filename.ts
node filename.js
出力結果
Hello, world!
Promise型のアンラップ方法
Promise.allを使う
const promise1: Promise<string> = new Promise((resolve) => {
resolve('Hello, ');
});
const promise2: Promise<string> = new Promise((resolve) => {
resolve('world!');
});
Promise.all([promise1, promise2]).then((values) => {
// valuesは[string, string]型の配列であることが保証される
const message = values.join('');
console.log(message); // "Hello, world!"が出力される
});
複数のPromiseのうち、最初に解決されたものを処理したい場合に有効な方法です。
const promise1: Promise<string> = new Promise((resolve) => {
setTimeout(() => resolve('Hello, '), 1000);
});
const promise2: Promise<string> = new Promise((resolve) => {
setTimeout(() => resolve('world!'), 500);
});
Promise.race([promise1, promise2]).then((value) => {
// valueはstring型であることが保証される
console.log(value); // "world!"が出力される
});
自作のヘルパー関数を使う
上記の方法でニーズを満たせない場合は、自作のヘルパー関数を作成する方法もあります。
function unwrapPromise<T>(promise: Promise<T>): T {
const result = await promise;
return result;
}
const promise: Promise<string> = new Promise((resolve) => {
resolve('Hello, world!');
});
const value = unwrapPromise(promise);
console.log(value); // "Hello, world!"が出力される
typescript promise