Есть ли способ сделать intellisense осведомленным о членах экземпляра интерфейса с динамическими индексами? - PullRequest
1 голос
/ 05 апреля 2019

Я работаю над угловым проектом и использую интерфейс для определения конфигурации модуля.Интерфейс предназначен для сопоставления имен с объектами и довольно прост:

export interface NamedRoutes {
  [routeName: string]: NamedRoute;
}

Когда я создаю экземпляр этого интерфейса, intellisense не может разрешить элементы экземпляра, когда я его использую.Например:

const routes: NamedRoutes {
  someRoute: {...}
};

const someRoute = routes. // no intellisense support here

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

Когда я опускаю ввод константы, intellisense может предложить правильные члены.Насколько я знаю, это потому, что имена индексов интерпретируются как символы, а не строки.Недостатком является то, что пользователи моего API получат поддержку компилятора только для ошибок, когда они передают объекты моему методу конфигурации, который в случае нашего проекта может находиться в совершенно ином месте, чем создание объекта.На мой взгляд, это был бы очень плохой UX для API.

Я пытался использовать различные расширенные типы, такие как Record<string, NamedRoute> и <T extends string = string> (для индекса).

Я надеюсьЯ ясно дал понять, в чем моя проблема и чего я пытаюсь достичь.Есть ли более эффективный способ сделать это?

PS: использование типа вместо интерфейса было бы вариантом для нашего проекта.

1 Ответ

1 голос
/ 05 апреля 2019

Вы можете предоставить пользователям вспомогательную функцию, которую они используют для создания NamedRoutes экземпляров, вместо того, чтобы позволить им использовать аннотацию NamedRoutes.Примерно так:

// I like examples that compile, so here's something random:
interface NamedRoute {
    whoKnows: string; 
}

export interface NamedRoutes {
    [routeName: string]: NamedRoute;
}

// helper function that just returns the input but makes sure it conforms to NamedRoutes    
const asNamedRoutes = <T extends NamedRoutes>(t: T) => t;

// correct use
const routes = asNamedRoutes({
    someRoute: { whoKnows: "blah" }
});

routes.someRoute // IntelliSense is here, yay!

// incorrect use so you still get early errors
const badRoutes = asNamedRoutes({
    badRoute: { nobodyKnows: "whoops " } // error!
    // type { nobodyKnows: string } is not assignable to NamedRoute
})

Функция asNamedRoutes() по сути такая же, как принуждение людей передавать объект методу раньше, чем когда они обычно это делают, чтобы ошибки появлялись раньше.Есть вещи, которые вы можете сделать, чтобы аннотации NamedRoutes были менее возможными (такой эффект сделал бы NamedRoutes класс с закрытым членом), но это, вероятно, излишне.

Надеюсь, это поможет.Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...