基本上,我试图找到一种将函数类型用作泛型类型的方法,以找到具有我选择的约束的函数的返回类型。但是,我不确定这是否可能,因为我不明白通用函数参数在条件子句中如何工作。这是我目前正在尝试的:
type FooFormatter = <S extends string>(input: S) => `foo-${S}`;
type StringFormatter = <S extends string>(input: S, ...args: never) => string;
type ComputeFormatter<Input extends string, T extends StringFormatter> =
T extends (input: Input, ...args: never) => `${infer $Value}`
? $Value
: never;
type foo = ComputeFormatter<"hey", FooFormatter>; // this is `foo-${string}` but I want "foo-hey"
在
ComputeFormatter
中,我试图检查是否可以通过将函数的第一个参数覆盖为 T
类型来限制 Input
中的泛型。感谢您的帮助!
简短的回答,针对此功能,为 TS4.7 合并了一个 PR。与您的问题特别相关...
type Box<T> = ReturnType<typeof makeBox<T>>; // { value: T }
这非常接近#37181 的解决方案。它会让我们做...
return { value }; }; // Can we do it or something similar? Currently doesn't compile :( type MakeBox<T> = ReturnType<typeof makeBox<T>> // As it now allows us to do (no generics though) const stringMakeBox = makeBox<string>; type MakeBox = ReturnType<typeof stringMakeBox> // And even more relevant to support generics if we can now do: type MakeBox = ReturnType<typeof makeBox<string>>
是的,您确实可以使用该模式来捕获泛型函数的泛型返回类型。这是以前不可能的事情。我将更新 PR 描述以包含示例。
我找不到任何关于这是否适用于函数的类型别名,或者仅适用于运行时函数(用
typeof
推断)的信息,但您可能只使用实际的运行时实现并根据需要使用typeof
这是在夜间构建上进行的工作,请注意,您仍然需要一个运行时实现,无论它是否实际实现任何内容都取决于您,它可能是一些不返回任何内容的模拟函数
type FooFormatter = <S extends string>(input: S) => `foo-${S}`;
const FooFormatterImplementation: FooFormatter = {} as any; //mock implementation
type StringFormatter = <S extends string>(input: S, ...args: never) => string;
type foo = ReturnType<typeof FooFormatterImplementation<"hey">>
// ^? `type foo = "foo-hey"`
type-fest
拥有的一些类型(如果您还没有的话)。特别是
Split
Change case utilities
,通读该库,看起来您对类型有很好的了解,我认为您实际上可能受到 TS 版本的 Deno 的限制。
有很多解决方法,但我不确定它们是否真的适用于您的用例。
这不依赖于 TS4.7 万岁!
type FooFormatter = <S extends string>(input: S) => `foo-${S}`;
type BarFormatter = <S extends string>(input: S) => `bar-${S}`
export interface Formatters {
FooFormatter: FooFormatter,
BarFormatter: BarFormatter
}
// then anyone wanting to add a custom formatter, has to modify and reexport the interface,
// this is similiarly done in @react-mui, using module augmentation
// https://www.typescriptlang.org/docs/handbook/declaration-merging.html
function takeInnerTest<T extends string, FmtKey extends keyof Formatters>(input: T, formatter: FmtKey)
{
type formattersDiscriminated = {
[K in keyof Formatters]: Formatters[K]
}[FmtKey]
const __mockFunction: formattersDiscriminated = ((...args: any[]) => undefined) as any
const __mockReturn = __mockFunction(input)
type String = ReturnType<typeof __mockFunction>
type ReturnValue = Extract<typeof __mockReturn, String>
return null! as ReturnValue
}
const foo3 = takeInnerTest("hey", "FooFormatter")
type foo3 = typeof foo3
// ^?
const foo4 = takeInnerTest("hey", "BarFormatter")
type foo4 = typeof foo4
// ^?