Поскольку T
отображается в двух позициях для вызова функции (как автономно, так и в K
), в основном есть две позиции, которые могут определять тип T
. Теперь, как правило, машинопись может обрабатывать такие случаи для простых ситуаций, но использование сопоставленного типа заставит его отказаться от вывода типа K
.
Существует несколько возможных решений, одно из которых вы обнаружили, то есть сначала исправить T
. Вы сделали это с классом, вы также можете сделать это с функцией, которая возвращает функцию:
function indexTraverseOnly2<T extends TraversableType>(startObj: T) {
return function <K extends TraversablePropNames<T>>(key: K): T[K] {
return startObj[key];
}
}
let r3 = indexTraverseOnly2(t2)('typeThree'); // TypeThree
Другим решением было бы указать ограничение, что K
должен вводить в T
значение TraversableType
другим способом, можно сказать, что T
должен расширять Record<K, TraversableType>
, означая, что ключ K
должен иметь тип TraversableType
независимо от любых других свойств.
function indexTraverseOnly<T extends Record<K, TraversableType>, K extends keyof any>(startObj: T, key: K): T[K] {
return startObj[key];
}
Редактировать
Для обхода нескольких типов вам потребуется определить несколько перегрузок. К сожалению, нет способа сделать это за одну перегрузку, так как параметры взаимозависимы. Вы можете определить до разумного числа перегрузок:
function indexTraverseOnly<T extends Record<K, TraversableType & Record<K2,TraversableType& Record<K3,TraversableType>>>, K extends keyof any, K2 extends keyof any, K3 extends keyof any>(startObj: T, key: K, key2:K2, key3:K3): T[K][K2][K3]
function indexTraverseOnly<T extends Record<K, TraversableType & Record<K2,TraversableType>>, K extends keyof any, K2 extends keyof any>(startObj: T, key: K, key2:K2): T[K][K2]
function indexTraverseOnly<T extends Record<K, TraversableType>, K extends keyof any>(startObj: T, key: K): T[K]
function indexTraverseOnly(startObj: any, ...key: string[]): any {
return null;
}
let t2: TypeTwo;
let r1 = indexTraverseOnly(t2, 'typeOne'); // TypeOne
let r2 = indexTraverseOnly(t2, 'typeOne', 'typeTwo'); // TypeTwo
let r3 = indexTraverseOnly(t2, 'typeOne', 'typeTwo', 'typeThree'); // TypeThree