🐾
typescriptの型定義ファイルでMixinを定義したかった
はじめに
typescript/javascript万年初心者です。
これはタイトルの通りで、うまいやり方がわからなかったという内容です。
(ご存知の方がいれば教えていただきたい。)
型定義したい理由
jsを使用しているプロジェクトを開発している中で、ts-checkを使用して解析してもらいたいと思いました。(最近存在を知ったので使いたいだけ)
外部のライブラリを使用しているが,そのライブラリの型定義やソースは非公開でドキュメントだけ存在するのでその仕様をd.tsの型定義ファイルとして用意したいのです。
問題設定
jsでは以下のような実装をしている。
class AAA extends ZZZMixin(BBB) {
hoge() {
console.log(ZZZMixin.hoge);
this.zzzfunc();
}
}
- ZZZMixinはstaticな変数を持っている。(ZZZMixin.hoge)
- ZZZMixinをmixinしたクラスはzzzfuncを呼べる。
- もちろんmixinされたBBBクラスのプロパティにもアクセスできる。
以上をd.tsで定義してみたい
tscで生成してみる
セットアップ
mkdir mixintest
cd mixintest
npx tsc --init
tsconfig.js
{
"include": ["src"],
"compilerOptions": {
"emitDeclarationOnly": true,
"declaration": true,
"outDir": "./out",
"target": "esnext",
"allowJs": true,
"checkJs": true
}
}
トランスパイル元のjsを用意
const ZZZMixin = superClass =>
class extends superClass {
static hoge = 'Hoge';
zzzfunc() {}
};
トランスパイルで型定義ファイルを生成と結果
以下コマンドで生成する。tsconfig.jsonにしたがって、./out以下にzzzmixin.d.tsが生成される。
npx tsc
結果
tscコマンドで以下のようなファイルが生成された。
zzzfuncは補完されるのでいいが、ZZZMixin.hogeでアクセスすることはできないしstaticでもない。
declare function ZZZMixin(superClass: any): {
new (): {
[x: string]: any;
zzzfunc(): void;
};
[x: string]: any;
hoge: string;
};
妥協した結果
mixinの中身はBBBしか使用していないので以下で妥協している。
決め打ちでBBBをextendsしたクラスを定義しているので、Mixinとは名ばかりの定義になってしまった。
declare class Apple {
apple(): ()=>string
}
export class ZZZMixin extends Apple {
static hoge: "hoge"
zzzfunc: ()=>void
}
type Constructor = new (...args: any[]) => {};
export function ZZZMixin<TBase extends Constructor>(Base: TBase): typeof ZZZMixin
Discussion