当从函数的参数声明为泛型时,不会推断函数的返回类型
Returned type of a function is not inferred when it's declared as generic from the function's argument
问题
我有以下两种。
interface SchemaItem {
name: string,
value: string
}
type Result<T extends SchemaItem[]> = {
[K in T[number] as K['name']]: K['value']
}
我有一个函数应该从 SchemaItem[]
参数创建 Result
类型的值。
function createResult<T extends SchemaItem[]>(schemaItems: T): Result<T> {
// implementation doesn't matter for this question
return {} as Result<T>
}
当我这样测试时,Result
类型按预期工作。
// ResultType = { foo: "Foo", bar: "Bar" }
type ResultType = Result<[
{ name: 'foo', value: "Foo" },
{ name: 'bar', value: "Bar" },
]>
但是当我用相同的数据测试函数时,返回值没有正确推断。
// result is of type Result<{ name: string; value: string }[]>
const result = createResult([
{ name: 'foo', value: "Foo" },
{ name: 'bar', value: "Bar" },
])
是否可以让 TypeScript 将 result
的类型推断为 { foo: "Foo", bar: "Bar" }
或者这是设计限制?
我试过的
我想也许问题在于 SchemaItem
的 name
属性 被声明为 string
,这就是我想出的。
interface SchemaItem<T extends string = string> {
name: T,
value: string
}
type ArrayToUnion<T> = T extends Array<infer R> ? R : never
type Result<T extends SchemaItem[]> = ArrayToUnion<T> extends SchemaItem<infer R> ? { [key in R]: string } : never
但这并没有帮助,result
值的类型 { [x: string]: string }
也好不到哪儿去。
您可以从 readonly
数组类型扩展您的泛型,然后通过在输入上使用 as const
assertion 向函数提供对象文字类型的只读数组。 (使用 as const
断言告诉编译器从字面上推断类型。)
interface SchemaItem {
name: string,
value: string
}
type Result<T extends readonly SchemaItem[]> = {
[K in T[number] as K['name']]: K['value']
}
type ResultType = Result<[
{ name: 'foo', value: "Foo" },
{ name: 'bar', value: "Bar" },
]>
function createResult<T extends readonly SchemaItem[]>(schemaItems: T): Result<T> {
return {} as Result<T>
}
const result = createResult([
{ name: 'foo', value: "Foo" },
{ name: 'bar', value: "Bar" },
] as const);
result.bar; // "Bar"
result.foo; // "Foo"
问题
我有以下两种。
interface SchemaItem {
name: string,
value: string
}
type Result<T extends SchemaItem[]> = {
[K in T[number] as K['name']]: K['value']
}
我有一个函数应该从 SchemaItem[]
参数创建 Result
类型的值。
function createResult<T extends SchemaItem[]>(schemaItems: T): Result<T> {
// implementation doesn't matter for this question
return {} as Result<T>
}
当我这样测试时,Result
类型按预期工作。
// ResultType = { foo: "Foo", bar: "Bar" }
type ResultType = Result<[
{ name: 'foo', value: "Foo" },
{ name: 'bar', value: "Bar" },
]>
但是当我用相同的数据测试函数时,返回值没有正确推断。
// result is of type Result<{ name: string; value: string }[]>
const result = createResult([
{ name: 'foo', value: "Foo" },
{ name: 'bar', value: "Bar" },
])
是否可以让 TypeScript 将 result
的类型推断为 { foo: "Foo", bar: "Bar" }
或者这是设计限制?
我试过的
我想也许问题在于 SchemaItem
的 name
属性 被声明为 string
,这就是我想出的。
interface SchemaItem<T extends string = string> {
name: T,
value: string
}
type ArrayToUnion<T> = T extends Array<infer R> ? R : never
type Result<T extends SchemaItem[]> = ArrayToUnion<T> extends SchemaItem<infer R> ? { [key in R]: string } : never
但这并没有帮助,result
值的类型 { [x: string]: string }
也好不到哪儿去。
您可以从 readonly
数组类型扩展您的泛型,然后通过在输入上使用 as const
assertion 向函数提供对象文字类型的只读数组。 (使用 as const
断言告诉编译器从字面上推断类型。)
interface SchemaItem {
name: string,
value: string
}
type Result<T extends readonly SchemaItem[]> = {
[K in T[number] as K['name']]: K['value']
}
type ResultType = Result<[
{ name: 'foo', value: "Foo" },
{ name: 'bar', value: "Bar" },
]>
function createResult<T extends readonly SchemaItem[]>(schemaItems: T): Result<T> {
return {} as Result<T>
}
const result = createResult([
{ name: 'foo', value: "Foo" },
{ name: 'bar', value: "Bar" },
] as const);
result.bar; // "Bar"
result.foo; // "Foo"