Я пытаюсь выяснить, почему следующий код не будет работать так, как я ожидаю. Тип пересечения, кажется, работает нормально (когда переопределяется внутри функции), однако использование его в качестве значения по умолчанию для аргумента generi c не подходит.
interface A {
a: string
}
interface B {
b: string
}
interface C {
c: string
}
function returnStuff<T = A & B>(
optionalReturnFn?: (value: T) => T): (value: T) => T {
const defaultReturnFn = (value: T) => {
value.a // <----- why does this a error
return value
}
return optionalReturnFn ? optionalReturnFn : defaultReturnFn
}
function returnStuff2<T extends A & B>(
optionalReturnFn?: (value: T) => T): (value: T) => T {
const defaultReturnFn = (value: T) => {
value.a // <----- while this one does not
return value
}
return optionalReturnFn ? optionalReturnFn : defaultReturnFn
}
const bc: B & C = { b: 'b', c: 'c' } // <--- valid intersection type
// Works as expected when calling fn but DOESN't work as I'd expect internally to fn
returnStuff<B & C>((value) => {
return value
})
// Doesn't work when calling fn but DOES work as expected internally to fn
returnStuff2<B & C>((value) => {
return value
})
Вот TS Playground , если вы хотите поиграть с ошибками.
ОБНОВЛЕНИЕ : я закончил тем, что добавил защиту типа и использовал ее в определении функции returnStuff
.
...
function isDefaultType<DefaultType>(
record: any,
keys: string[]
): record is DefaultType {
return every(keys, (key) => key in record)
}
function returnStuff<T = A & B>(
optionalReturnFn?: (value: T) => T): (value: T) => T {
const defaultReturnFn = (value: T) => {
if(isDefaultType<T>(value, ['a', 'b']) {
value.a // <----- no longer throws an error
return value
}
}
return optionalReturnFn ? optionalReturnFn : defaultReturnFn
}