Как определить тип свойства объекта - PullRequest
0 голосов
/ 15 мая 2019

У меня есть следующий фрагмент кода, и я хотел бы вывести тип свойства объекта.Как вы можете видеть, предполагаемый тип v в моем примере - {}.Как я могу написать myValue, чтобы Typescript выводил C во время компиляции?


const myValue = <T1, T2>(prop: string, obj: T1): T2 => {
  return obj[prop]
}

interface C {
  readonly c: string
}

interface TestInt {
  readonly a: string
  readonly b: number
  readonly c: C
}

const test: TestInt = {
  a: 'a',
  b: 1,
  c: {
    c: 'c',
  },
}

const v = myValue('c', test) // const v: {}

1 Ответ

1 голос
/ 15 мая 2019

Вывод параметра типа работает лучше всего, когда у вас есть фактическое значение типа, который вы пытаетесь вывести.Наличие T2 типа возвращаемого значения функции, вероятно, будет проблемой.Если вы не вызовете myValue() в контексте, который ожидает возвращаемого значения типа C, мало надежды на то, что компилятор выведет C для него ... вывод параметра типавозвращаемое значение называется контекстной типизацией , и, к сожалению, в const v = myValue(...) отсутствует контекстный тип для v.Это может быть что угодно.

Так какие типы у вас действительно есть значения?Поскольку вы вызываете myValue() с параметрами prop и obj, первое, что нужно сделать, это дать obj универсальный тип, такой как T, и дать prop другой универсальный тип, такой как K ...и выведите T и K из obj и prop соответственно.

Обратите внимание, что вы предполагаете, что prop должен быть одним из ключей obj, поэтому у вас есть естественное ограничение для типа K, а именно, что оно должно расширятьсяkeyof T.

Наконец, тип возврата вашей функции может быть получен из других типов.Предполагается, что это тип свойства T, ключ которого - K.Это может быть представлено как T[K] ( тип поиска ).

Вот окончательная версия функции:

const myValue = <T, K extends keyof T>(prop: K, obj: T): T[K] => {
    return obj[prop];
}

Обратите внимание на сходство между этой функцией ифункция getProperty(), упомянутая в документации для keyof и типов поиска .Единственная разница - это порядок параметров (ну, и тот факт, что возвращаемый тип выводится вместо аннотированного .... и имя функции, я думаю).

Когда мы используем это определение myValue() мы получаем:

interface C {
    readonly c: string
}

interface TestInt {
    readonly a: string
    readonly b: number
    readonly c: C
}

const test: TestInt = {
    a: 'a',
    b: 1,
    c: {
        c: 'c',
    },
}

const v = myValue('c', test) // const v: C

, как вы хотели.

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

...