From d463a0db30f0728a1aaee8129004c273b7bdfc39 Mon Sep 17 00:00:00 2001 From: takejohn <105504345+takejohn@users.noreply.github.com> Date: Sat, 30 Mar 2024 17:17:43 +0900 Subject: [PATCH] =?UTF-8?q?=E3=81=99=E3=81=B9=E3=81=A6=E3=81=AE=E3=83=97?= =?UTF-8?q?=E3=83=AD=E3=83=91=E3=83=86=E3=82=A3=E3=82=92=E3=83=81=E3=82=A7?= =?UTF-8?q?=E3=83=83=E3=82=AF=E3=81=97=E3=81=A6=E3=81=8B=E3=82=89=E3=82=A8?= =?UTF-8?q?=E3=83=A9=E3=83=BC=E9=80=81=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config.ts | 78 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 27 deletions(-) diff --git a/src/config.ts b/src/config.ts index 1f17f5c..1b1989d 100644 --- a/src/config.ts +++ b/src/config.ts @@ -40,23 +40,44 @@ class Type { } } -function checkProperty(config: Object, key: K, type: Type): config is { [J in K]: Config[K] } { - const result = key in config && type.check(config[key as string]); - if (!result) { - warnWithPrefix(`config.json: Property '${key}': ${type.name} required`); +class OptionalProperty { + protected readonly key: K; + protected readonly type: Type + + public constructor(key: K, type: Type) { + this.key = key; + this.type = type; + } + + check(config: Object): config is { [J in K]?: Config[K] } { + const key = this.key; + if (!(key in config)) { + return true; + } + const result = this.type.check((config as { [J in K]?: unknown})[key]); + if (!result) { + warnWithPrefix(`config.json: The type of property '${key}' must be ${this.type.name}`); + } + return result; } - return result; } -function checkOptionalProperty(config: Object, key: K, type: Type): config is { [J in K]?: Config[K] } { - if (!(key in config)) { - return true; +class Property extends OptionalProperty { + check(config: Object): config is { [J in K]: Config[K] } { + const result = this.key in config && this.type.check((config as { [J in K]?: unknown })[this.key]); + if (!result) { + warnWithPrefix(`config.json: Property '${this.key}': ${this.type.name} required`); + } + return result; } - const result = type.check(config[key as string]); - if (!result) { - warnWithPrefix(`config.json: The type of property '${key}' must be ${type.name}`); - } - return result; +} + +type Intersection

= P extends [infer Q, ...infer R] ? Q & Intersection : unknown; + +function checkProperties

[]>(config: Object, ...properties: P): + config is object & Intersection<{ [I in keyof P]: P[I] extends OptionalProperty ? { [J in K]: Config[K] } : never }> { + // メッセージを表示するためすべてのプロパティをチェックしてから結果を返す + return properties.map(p => p.check(config)).every(c => c); } function setProperty(config: Object, key: K, value: Config[K]): asserts config is { [L in K]: Config[K] } { @@ -67,20 +88,23 @@ function validate(config: unknown): Config { if (!(config instanceof Object)) { warnWithPrefix('config.json: Root object required'); } else if ( - checkProperty(config, 'host', Type.string) && - checkOptionalProperty(config, 'serverName', Type.string) && - checkProperty(config, 'i', Type.string) && - checkOptionalProperty(config, 'master', Type.string) && - checkProperty(config, 'keywordEnabled', Type.boolean) && - checkProperty(config, 'reversiEnabled', Type.boolean) && - checkProperty(config, 'notingEnabled', Type.boolean) && - checkProperty(config, 'chartEnabled', Type.boolean) && - checkProperty(config, 'serverMonitoring', Type.boolean) && - checkOptionalProperty(config, 'checkEmojisEnabled', Type.boolean) && - checkOptionalProperty(config, 'checkEmojisAtOnce', Type.boolean) && - checkOptionalProperty(config, 'mecab', Type.string) && - checkOptionalProperty(config, 'mecabDic', Type.string) && - checkOptionalProperty(config, 'memoryDir', Type.string) + checkProperties( + config, + new Property('host', Type.string), + new OptionalProperty('serverName', Type.string), + new Property('i', Type.string), + new OptionalProperty('master', Type.string), + new Property('keywordEnabled', Type.boolean), + new Property('reversiEnabled', Type.boolean), + new Property('notingEnabled', Type.boolean), + new Property('chartEnabled', Type.boolean), + new Property('serverMonitoring', Type.boolean), + new OptionalProperty('checkEmojisEnabled', Type.boolean), + new OptionalProperty('checkEmojisAtOnce', Type.boolean), + new OptionalProperty('mecab', Type.string), + new OptionalProperty('mecabDic', Type.string), + new OptionalProperty('memoryDir', Type.string) + ) ) { setProperty(config, 'wsUrl', config.host.replace('http', 'ws')); setProperty(config, 'apiUrl', config.host + '/api');