Что я могу использовать в машинописи, чтобы показать связь между значениями двух интерфейсов - PullRequest
0 голосов
/ 22 апреля 2020
interface baseVal {
    val: string
}

interface parentA{
    checker: baseVal
}

interface parentB{
    someone: baseVal
}

let test = <T extends parentA | parentB>(param: T) => {
    const keys = Object.keys(param) as (keyof T)[]
    keys.forEach(key => {
        let data = param[key] as baseVal // error 

    })
}

В настоящее время я получаю сообщение об ошибке "let data = param [key] as baseVal". Это то, что говорится в ошибке:

Преобразование типа 'T [keyof T] 'Тип' baseVal 'может быть ошибкой, поскольку ни один из типов не совпадает с другим. Если это было сделано преднамеренно, сначала преобразуйте выражение в «неизвестное».

Почему машинопись не понимает, что значения в интерфейсах имеют одинаковый тип? Как я могу создать интерфейсы, чтобы машинописный текст знал об этих отношениях?

1 Ответ

1 голос
/ 22 апреля 2020

На самом деле, что происходит, когда у вас есть тип parentA | parentB - это тип без ключей вообще, потому что union (pipe) не ведет себя так, как вы ожидаете в случае интерфейсов. См. https://www.typescriptlang.org/docs/handbook/advanced-types.html#union -типы :

Если значение имеет тип A | B, мы знаем только наверняка, что у него есть члены, которые есть и у A, и у B. В этом примере Bird имеет члена с именем fly. Мы не можем быть уверены, является ли переменная типа Bird | Fi sh имеет метод fly. Если переменная действительно Fi sh во время выполнения, то вызов pet.fly () не удастся

Вы можете убедиться в этом сами, введя строку let x = param.someone.val;. Вы увидите жалобу intellisense, что param не имеет члена someone. Это потому, что param может иметь тип parentA, и в этом случае эта строка выдаст исключение во время выполнения, поскольку param.someone не определено. Короче говоря, вы не можете использовать здесь тип объединения.

Одна из основных целей машинописи - предотвратить ошибки времени выполнения из-за неправильной типизации, поэтому, если объект, передаваемый в функцию, может быть одного из двух типов, вы не может получить доступ к полю, принадлежащему только одному из этих типов. В некоторых случаях вы можете использовать проверку типов, как описано на связанной странице в этой ситуации, но в вашем случае проблему не так легко решить. Обратите внимание, что вы перебираете ключи param. Представьте, что у типов было более одного ключа. Как машинописный текст разрешит тип param [key]? В предоставленном коде человек может видеть, что это за тип, но в целом такой подход недопустим. Поэтому, если вы хотите сохранить код примерно так, как он есть, вам может понадобиться go с чем-то вроде:

interface baseVal {
    val: string
}

interface parentA{
    checker: baseVal;
}

interface parentB{
    someone: baseVal;
}

interface parent {
  [key: string]: baseVal;
}

let test = <T extends parent>(param: T) => {
    const keys = Object.keys(param) as (keyof T)[]
    keys.forEach(key => {
        let data = param[key] as baseVal; 
    })
} 

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

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