Рассмотрим следующие два типа:
type CoolFunction = (c: CoolType) => any
type CoolType = {
[key: string]: CoolType | CoolFunction
}
// can be nested many times
const example: CoolType = {
foo: {
bar: {},
dog: (c) => c.foo
},
baz: (c) => c.foo.bar
}
Возможно ли построить функцию, которая принимает значение CoolType
, которое автоматически предоставит тип аргумента, переданного в CoolFunction
, без необходимости предоставить аргумент типа для функции?
function doCoolStuff<T extends CoolType>(myCoolObj: T) {
// recursively search for and call all CoolFunctions in myCoolObj with myCoolObj as param
}
doCoolStuff({
someProperty: {
foo: {},
},
somethingElse: {
// the type of c should automatically be inferred to be the object we're currently creating
test: (c) => c.someProperty.foo
}
})
Я предполагаю, что CoolType
придется принять некоторые параметры типа, а затем передать их рекурсивно внутрь, но мои попытки до сих пор всегда заканчиваются на типе будучи any
или never
. Пример:
type CoolFunction<C extends CoolType<any, any>> = (c: C) => any;
// an attempt to provide the entire object shape,
// as well as the subtree of the property we're currently typing
type CoolType<
Tree extends CoolType<any, any>,
Subtree extends CoolType<any, any>
> = {
[K in keyof Subtree]: Subtree[K] extends CoolFunction<Tree>
? CoolFunction<Tree>
: Subtree[K] extends CoolType<any, any>
? CoolType<Tree, Subtree[K]>
: never
};
function doCoolStuff<C extends CoolType<any, any>>(myCoolObj: C) {
// recursively search for and call all CoolFunctions in myCoolObj with myCoolObj as param
}
doCoolStuff({
foo: {
bar: {}
},
// c: any
baz: c => console.log(c.foo.bar)
});
Есть указатели? Возможно ли то, что я пытаюсь сделать?