Есть ли способ обнаружить опечатки в строковых литералах в TypeScript

#typescript #types

#typescript #типы

Вопрос:

У меня есть объект как со статически известными, так и (иногда) динамическими свойствами.

Я надеюсь, что TypeScript поможет отловить опечатки. Очевидно, что это невозможно для свойств, добавленных во время выполнения, но опечатки в строковых литералах теоретически могут быть обнаружены.

Подход, который я использую, заключается в том, чтобы попытаться разрешить динамические строки, но запретить типы строковых литералов, которых нет в списке благословенных («foo» и «bar» в примере).

Например, что-то вроде этого синтаксиса может работать (но это не так):

 type Options = {
    foo?: boolean;
    bar?: boolean;
    [index: NotLiteral<string>]: boolean;
}

type NotLiteral<T> = string extends T ? never : T


const o: Options = {};
o["fooTypo"] = true; // I wish this didn't typeCheck
o[callApi()] = true; // should be OK


declare function callApi(): string;
 

Эти типы индексов могут быть string или number , вероятно, преодолимы (вероятно, есть обходной путь), но более глубокая проблема заключается в том, что string расширяются типы строковых литералов, что на самом деле не имеет смысла.

 const x: NotLiteral<"foo"> = "foo"; // type is "string", but should probably be "never"
 

Правила для ‘extends’, похоже, не совпадают с правилами назначения здесь (почему?):

 const x: "foo" = callApi() // type error (good) even though "string" extends "foo"
 

Ссылка на игровую площадку: https://www.typescriptlang.org/play/index.html

Комментарии:

1. Как бы вы или TypeScript узнали, что "fooTypo" это опечатка "foo" , а не правильно написанное свойство index? Также неясно, что вы имеете в виду string extends string ? never : string .

2. если бы мы могли ввести свойство index как NotLiteral, тогда оно должно было бы иметь тип ‘string’, а не тип ‘foo’. Такого рода вещи (независимо от того, является ли строка литералом или нет), по-видимому, могут быть обнаружены для присваиваемости, но не для extends (см. ^)

3. …что? NotLiteral<string> это то же never самое, что и, он не собирается волшебным образом подбирать каждое значение, которое вы пытаетесь присвоить, и переоценивать тип.