Краткий ответ: Partial<(a: string) => number>
оценивается как {}
, пустой тип объекта, такой как unknown
с null
и undefined
исключенным.
Более длинный ответ:
Partial<T>
- это отображенный тип , определенный как {[K in keyof T]?: T[K]}
. Он перебирает свойства T
и делает каждое из них необязательным. В этом случае, однако, keyof ((a: string)=>number)
есть never
;у него нет свойств. (Ну, типы функций do имеют свойства интерфейса Function
, такие как bind
, call
, length
и т. Д., И свойства интерфейса Object
, такие как toString
и valueOf
и т. Д. Но эти свойства обычно бесполезны для итерации, поэтому они подавляются.) Поэтому Partial<(a: string)=>number>
возвращает тип объекта без свойств: пустой тип {}
.
Пустой тип {}
действует почти так же, как unknown
, в этом ему присваивается почти все . Это потому, что типы объектов в TypeScript «открыты», и вы можете добавить свойство к типу, не делая его несовместимым. Таким образом, в
interface Foo {a: string}
interface Bar extends Foo {b: string}
значение типа Bar
({a: string, b: string}
) также присваивается типу Foo
({a: string}
). Если вы доведите это до логического завершения, любой тип объекта вообще будет назначаться пустому типу объекта {}
. Кроме того, примитивные типы, такие как string
и number
, считаются назначаемыми типам объектов, если их свойства совместимы. Поскольку типы string
и number
имеют свойства (например, length
и toFixed
и т. Д.), Они также могут быть назначены пустому типу объекта. Только null
и undefined
фактически выдают ошибки времени выполнения при попытке прочитать из них свойства, поэтому эти два значения не считаются назначаемыми {}
.
Если вы хотите создавать рекурсивные сопоставленные типы, вы должны решить, что вы хотели бы видеть, когда вы нажмете свойство с типом функции, а затем использовать условный тип , чтобы это произошло. Очевидная вещь, которую нужно сделать, это просто сохранить тип функции метода как есть (хотя, возможно, наличие метода должно быть необязательным? Не уверен.)
Так что это будет выглядеть как
type DeepPartial2<T> = T extends Function ? T : {
[K in keyof T]?: DeepPartial2<T[K]>
}
interface Foo {
name: string,
age: number,
yell(): void,
friend: Foo
}
type DPFoo = DeepPartial2<Foo>;
/*
type DPFoo = {
name?: string | undefined;
age?: number | undefined;
yell?: (() => void) | undefined;
friend?: DPFoo | undefined;
}
*/
Хорошо, надеюсь, это поможет;удачи!
Ссылка на код