

AWSのS3クライアントモジュールにて、下記関数があるのですが、この書き方だとerrが確実にcallbackに入ってくるので、`err?:
Error`となっているべきではないか、  
と考えてしまいます。

[code]

    upload(params: S3.Types.PutObjectRequest,
           options?: ManagedUpload.ManagedUploadOptions,
           callback?: (err: Error, data: ManagedUpload.SendData) => void): ManagedUpload;
    
[/code]

<https://github.com/aws/aws-sdk-
js/blob/50e46727e58bcaebd61876e669d60d528b300f62/lib/services/s3.d.ts#L39>

これでは `if (error) { /* エラーハンドリング */ } else { /* 正常な処理 */ }`
と実装した際、エラーハンドリングが常に呼ばれてしまう気がします。

どなたかこの疑問を解決していただけると幸いです。


CC BY-SA 4.0
2021-07-16T01:53:36.417
78219
2021-07-18T14:02:28.007
2021-07-16T06:53:14.577
19110
47314
question
typescript optional
aws-sdk-js で定義されている型が正しいか分からない


ソースコードや提示されているリンクから、 [AWS SDK for JavaScript
v2](https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-
guide/welcome.html) であるという前提で回答します。

こういうのは、だいたい API ドキュメントの方が正しく記述されていることが多いです。  
と言うことで、早速見てみましょう。  
<https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-
property>

> ## Callback (`callback`):
[code]

>     function(err, data) { ... }
>  
[/code]

>
> ### Parameters:
>
>   * err (`Error`) — an error or null if no error occurred.
>

と言うことで、 エラーが発生しなければ `err` パラメータには `null` が入るというのが、実際の動作になります。  
つまり、その型注釈は間違っています。

* * *

…と、それだけの回答だと寂しいので、実際に動作を試してみましょう。

AWS を利用するとお金がかかってしまうので、 S3 互換のオブジェクトストレージである
[MINIO](https://docs.min.io/docs/minio-docker-quickstart-guide.html) を Docker
でローカルに立ちあげて、 AWS SDK v2 でアクセスしてみます。

[code]

    docker run --rm -d -p 9000:9000 minio/minio server /data
    npm install aws-sdk
    
[/code]

[code]

    var AWS = require("aws-sdk");
    var s3 = new AWS.S3({
        credentials: new AWS.Credentials("minioadmin", "minioadmin"),
        endpoint: new AWS.Endpoint("http://127.0.0.1:9000"),
    });
    var t = s3.listBuckets((err, data) => {
        console.log({err, data});
    });
    
[/code]

[![](https://i.stack.imgur.com/hOBOh.png)](https://i.stack.imgur.com/hOBOh.png)

このように、 [`listBuckets` も callback の `err` パラメータは 非null
表記](https://github.com/aws/aws-sdk-js/blob/v2.947.0/clients/s3.d.ts#L487)
であるのにもかかわらず、 実際の動作では `err` パラメータに `null` が入っていることがわかります。

* * *

…で、 何故こんなことになっているかというと、JavaScript API v2 の GitHub リポジトリを見ていただければわかるとおり、 元のソースは
TypeScript ではなく、 JavaScript なんですよね。  
このため、型の情報は JSDoc コメントで書かれている情報が元になっています。

(TypeScript もそうですが、) JavaScript の型定義ファイルによる型注釈は、 IDE のコード補完や Lint
などに使われる一方で、コードの実行には何の影響も与えません。  
このため、いくら `err` パラメータが型注釈で 「null 非許容」 と宣言されていたとしても、実行時に null が入っていればそれは null
として評価されます。  
すなわち、 `if (err) { /* エラーハンドリング */ } else { /* 正常な処理 */ }` と実装すれば、
正常な処理の方がキッチリ実行されます。

元々、 JavaScript は null 安全なコードを記述する世界ではないため、 JSDoc は null チェックを行わない動作がデフォルトです。  
このため、 JSDoc によって生成された *.d.ts の中には、 null 許容型ではなくても null や undefined
が返されてしまうものがよくあります。

なお、 TypeScript で再設計された [AWS SDK for JavaScript
v3](https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v3/developer-
guide/welcome.html) であれば、 コンパイル時に strict が指定されている
([tsconfig.es.json](https://github.com/aws/aws-sdk-
js-v3/blob/main/tsconfig.es.json),
[tsconfig.cjs.json](https://github.com/aws/aws-sdk-
js-v3/blob/main/tsconfig.cjs.json)) ので、この型注釈はかなり信頼できます。 (v3
の新機能としても明示的に書いていますし。)  
このため、 v3 を使えば null 安全なコードを書くことができるはずです。


CC BY-SA 4.0
2021-07-16T10:53:41.547
78232
2021-07-18T14:02:28.007
2021-07-18T14:02:28.007
8237
8237
78219
answer