На самом деле, что происходит, когда у вас есть тип 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;
})
}
(Обратите внимание, что это не подойдет, если у ваших реальных типов больше ключей с разными типами, но тогда ваш код все равно будет недействительным.)