Интерфейс машинописного текста с никогда не вводимыми полями - PullRequest
0 голосов
/ 14 июля 2020

Учитывая следующий интерфейс, какое будет допустимое присваиваемое значение?

interface A {
  x: number,
  y: never
}

Я ожидал, что const a: A = { x: 1 } будет работать, но при этом возникает ошибка, указывающая, что поле y является обязательным. Как только я помещаю туда y, он говорит, что значение не может быть присвоено never.

Мой реальный вариант использования выглядит примерно так:

interface Context<T extends MyRequest> {
  id: string;
  token: T extends AuthenticateRequest ? string : never;
}

interface AuthenticatedRequest extends MyRequest { ... }

Здесь я Я не могу создать значение для Context<MyRequest>, так как он говорит, что token отсутствует.

В настоящее время у меня есть обходной путь:

type Context<T extends MyRequest> = {
  id: string;
} & (T extends AuthenticatedRequest ? {
  token: string;
} : {})

, но по очевидным причинам это выглядит некрасиво. ..

Есть идеи, как мне это сделать правильно?

Ответы [ 3 ]

1 голос
/ 14 июля 2020

Тип never - представление пустого типа. Что это означает - нет значения, которое принадлежит этому типу, что означает, что у вас всегда будет ошибка компиляции, если вы его используете.

Вам нужен условный тип на более высоком уровне, учтите:

type Context<T extends MyRequest> = T extends AuthenticateRequest ? {
  id: string;
  token: string;
} : { id: string };

Такой подход снимает бремя установки undefined для token. Если требуется token, то для T extends AuthenticateRequest это строка, если нет, то поля token нет.

0 голосов
/ 15 июля 2020

Основываясь на пунктах, упомянутых @Titian Cernicova-Dragomir и @Maciej Sikora, обходной путь - это правильный способ go для определения типа, которое мне нужно. interface не может иметь поле типа never, так как ему нельзя присвоить допустимое значение, что делает интерфейс бесполезным.

Вот что я наконец использовал для своего кода:

type Context<T extends MyRequest> = Readonly<
  {
    logger: MyLogger;
    timestamp?: number;
  } & (T extends AuthenticatedRequest
    ? {
        token: Token;
        user: string;
      }
    : {}) &
    (T extends GameRequest
      ? {
          gameId: string;
        }
      : {}) &
    (T extends ETagRequest
      ? {
          etag: string;
        }
      : {}) &
    (T extends UnParameterizedRequest
      ? {}
      : {
          params: Record<string, string | undefined>;
        })
>;
0 голосов
/ 14 июля 2020

Вам нужно указать тип как строку или undefined. Тип never используется, когда переменной никогда не будет присвоено значение. Подробнее об этом здесь .

Думаю, этот подход должен решить вашу проблему.

interface A {
  x: number,
  y: string | undefined
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...