👀
.d.ts での可視性を制御する tsconfig の stripInternal 設定について
TSConfig の compilerOption に stripInternal という設定があります。
TSConfig Reference #Strip Internal
この設定を有効にすると、JSDoc に @internal
を指定したコード(クラス、メソッド、変数、関数)がコンパイル時に生成される .d.ts
へ出力されなくなります。
これにより、C# や Kotlin の internal
、Java の package private
のようなアクセス修飾子相当の振る舞いを TypeScript で実現できます。
TypeScript では、export
を使ってコンパイル後のモジュールを構成する必要がありますが、モジュール内部に閉じたアクセス制御を行うことはできません。stripInternal を設定することで、モジュール内でのみ公開するコードを明示的に指定できます。
例
demo.ts
export const extenalVariable = "foo";
/**
* この関数はモジュール内でしか利用できない
* @internal
*/
export const internalFunction = () => "bar";
/**
* このクラスはモジュール内でしか利用できない
* @internal
*/
export class InternalClass {
publicMethod() {
return true;
}
}
export class ExtenalClass {
publicMethod() {
return true;
}
/**
* このメソッドはモジュール内でしか利用できない
* @internal
*/
internalMethod() {
return true;
}
}
上記をコンパイルした場合、.d.ts
ファイルは以下になります。@internal
が指定された関数やクラス、メソッドが出力されていないことが分かります。これにより外部からは参照ができなくなります(コンパイルエラーになる)。
demo.d.ts
export declare const extenalVariable = "foo";
export declare class ExternalClass {
publicMethod(): boolean;
}
interface にも指定できますが、interface 定義にのみ反映されます。実装側で @internal
を指定し忘れていた場合でも静的解析でエラーなどは出ないため注意してください。
interface Interface {
publicMethod: () => boolean;
/**
* .d.ts には表示されない
* @internal
*/
internalMethod: () => boolean;
}
export class ExternalClass implements Interface {
publicMethod() {
return true;
}
// 明示的に JSDoc で指定していないため .d.tsに出力される
internalMethod() {
return true;
}
}
まとめ
コードが肥大化していくと、モジュール内だけで利用するロジックが出現してきて、外部から見えなくしたい場面が出てきます。TypeScript では stripInternal
設定をすることで制御できるようになるので、複数のモジュールを利用している場合の参考にどうぞ。
Discussion