Ограничьте типы ключей интерфейса для значений другого интерфейса - PullRequest
0 голосов
/ 29 марта 2020

Этот пример игровой площадки описывает то, что я пытаюсь сделать, но по сути я пытаюсь ограничить возможные ключи одного объекта значениями другого.

Возможно ли это?

Ответы [ 3 ]

0 голосов
/ 29 марта 2020

В TypeScript невозможно определить типы на основе значений времени выполнения, так как все типизации удаляются во время выполнения. То, что вы просите, совершенно невозможно.

Подумайте: а что если этот объект был извлечен с веб-сервера, который возвращал случайные значения? Как бы компиляция вообще работала? Вам нужно было бы подключиться к inte rnet? Поскольку нет проверки типов во время выполнения, она просто не работает.

Чтобы выполнить sh во время выполнения, как вы, кажется, wi sh, вы можете использовать обычный javascript. Например:

const accessors = data.map(o => o.accessor);

for (const cell of cells) {
    for (const key in cell) {
        if (!accessors.includes(key)) {
            // throw a runtime error
            throw new Error("This key is not a valid accessor!"); 
        }
    }
}
0 голосов
/ 29 марта 2020

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

const data = [
  {
    title: "First name",
    accessor: "firstname",
  },
  {
    title: "Last name",
    accessor: "surname",
  }
] as const

type Accessors = typeof data[number]["accessor"]

type ICell = Record<Accessors, string>

const cells: ICell[] = [
  {
    firstname: "Davy",
    surname: "James"
  },
  {
    firstname: "Billy",
    surname: "Cricket"
  }
]

Если вы не знаете структуру data во время компиляции, как указали другие ответы, вы не можете этого сделать. Также (как и любой другой объект) вы должны проверить, что любые другие данные, созданные во время выполнения, соответствуют типу данных ICell, и вы не можете проверить их во время выполнения, если это то, что вы пытаетесь сделать.

0 голосов
/ 29 марта 2020

Самое близкое, что я могу получить, это

type accessor = "surname" | "firstname"

interface IData { 
  title: string;
  accessor: accessor;
}

type ICell = Record<accessor, string>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...