Open12

TypeScriptでインポートしたJSONにnarrowingした型をつけたい

かがんかがん

モチベーション

これを

index.ts
import { createRule } from '@markuplint/ml-core';

export default createRule({
	meta: {
		"category": "validation"
	},
	// 略
});

こうしたかった

meta.json
{
	"category": "validation"
}
index.ts
import { createRule } from '@markuplint/ml-core';

import meta from './meta.json';

export default createRule({
	meta: meta,
	// 略
});

なぜかというと、ビルドせずともcategoryの情報だけの他のファイルから読み取りたいから。

かがんかがん

問題

TypeScriptでJSONのインポート自体は問題なくできる。
しかし、型付けが不完全

{
	"category": "validation"
}

をインポートした場合、型は

{
	"category": string
}

になる。

しかし、渡す先の型は

	readonly meta?: {
		readonly category?: 'validation' | 'style' | 'naming-convention' | 'a11y' | 'maintainability';
	};

こうしていたため、stringでは渡せない。

  1. JSONを絞り込む
  2. 渡す先の引数の型を string に広げてしまう。
  3. type assertionする
  4. ts-ignoreする

JSONの型を絞り込めればそれがいい。

TS内でいえば、 as const すればnarrowingできるので、そういうことがしたい

const meta = {
	category: 'validation',
} as const
かがんかがん

試したこと

どうにもうまく適用されなかった

.d.ts

https://zenn.dev/nbr41to/articles/17298052d392bc

.d.json.ts

https://www.totaltypescript.com/override-the-type-of-a-json-file

かがんかがん

いや、他のリポジトリで .d.json.ts を試したら正しく型付けが上書きされた
単にどこかの設定が悪い説あるな

(問題の切り分け、大事だなあ~)

かがんかがん

あ、他のディレクトリに置いちゃったからだめなのであって、同じディレクトリに置く必要あるのか

かがんかがん

そもそも .default のバグがある以上、ここでは使えないかも

かがんかがん

出力後もJSON importが残るから、JSからimportして実行したときにエラーになる可能性あるな