基于参数的显式 return 类型
Explicit return type based on arguments
给定一个接受对象数组的函数,并且 returns 一个对象,其键都对应于参数中每个对象的 属性...似乎有应该是获得更明确的 return 类型的方法。
函数-
function objectFromArray(arr: { key: string }[]) {
let obj: {[k: string]: true} = {};
for (let {key} of arr) {
obj[key] = true;
}
return obj;
}
如果我运行以下
let myArray = [{key: 'a'}, {key: 'b'}, {key: 'c'}];
let myObj = objectFromArray(myArray);
那么myObj
的类型就是
let myObj: {
[k: string]: true;
}
但我觉得有足够的信息可以让打字稿推断 myObj
的类型实际上是
let myObj: {
a: true;
b: true;
c: true;
}
我的问题是需要在 objectFromArray
函数中做什么才能根据参数派生显式 return 类型。为清楚起见,我不担心 return 类型的值,只担心获取显式键。
如果你想让它起作用,你需要 objectFromArray()
成为 arr
元素的 key
属性 处的 generic function in the type K
of the string literal 值:
function objectFromArray<K extends string>(arr: readonly { key: K }[]) {
let obj = {} as { [P in K]: true }; // have to assert this because it's not true yet
for (let { key } of arr) {
obj[key] = true;
}
return obj;
}
readonly { key: K }[]
中的readonly
只是表示我们并不特别要求传入的数组是可变的。这为我们稍后需要的输入提供了更多余地。
return 类型,{ [P in K]: true }
是一个 mapped type giving an object with a true
-valued property for each string literal type in K
. (You could also use the Record
utility type to give the equivalent Record<K, true>
). Since {}
is not a valid value of this type, you'll need a type assertion 告诉编译器将 obj
视为类型 { [P in K]: true }
.
然后当你创建 myArray
时,编译器的默认行为是将其类型扩展为 Array<{key: string}>
,完全忘记字符串文字类型 "a"
、"b"
,以及 "c"
。为防止这种情况,您可以使用 const
assertion:
let myArray = [{ key: 'a' }, { key: 'b' }, { key: 'c' }] as const;
/* let myArray: readonly [{
readonly key: "a";
}, {
readonly key: "b";
}, {
readonly key: "c";
}] */
注意 const
断言如何使 myArray
成为 readonly
数组,这就是放宽函数输入类型的原因。现在编译器已经足够了解 myArray
,让我们调用 objectFromArray()
:
let myObj = objectFromArray(myArray);
/* let myObj: {
a: true;
b: true;
c: true;
} */
成功!根据需要,myObj
已知具有 a
、b
和 c
类型的 true
属性。
给定一个接受对象数组的函数,并且 returns 一个对象,其键都对应于参数中每个对象的 属性...似乎有应该是获得更明确的 return 类型的方法。
函数-
function objectFromArray(arr: { key: string }[]) {
let obj: {[k: string]: true} = {};
for (let {key} of arr) {
obj[key] = true;
}
return obj;
}
如果我运行以下
let myArray = [{key: 'a'}, {key: 'b'}, {key: 'c'}];
let myObj = objectFromArray(myArray);
那么myObj
的类型就是
let myObj: {
[k: string]: true;
}
但我觉得有足够的信息可以让打字稿推断 myObj
的类型实际上是
let myObj: {
a: true;
b: true;
c: true;
}
我的问题是需要在 objectFromArray
函数中做什么才能根据参数派生显式 return 类型。为清楚起见,我不担心 return 类型的值,只担心获取显式键。
如果你想让它起作用,你需要 objectFromArray()
成为 arr
元素的 key
属性 处的 generic function in the type K
of the string literal 值:
function objectFromArray<K extends string>(arr: readonly { key: K }[]) {
let obj = {} as { [P in K]: true }; // have to assert this because it's not true yet
for (let { key } of arr) {
obj[key] = true;
}
return obj;
}
readonly { key: K }[]
中的readonly
只是表示我们并不特别要求传入的数组是可变的。这为我们稍后需要的输入提供了更多余地。
return 类型,{ [P in K]: true }
是一个 mapped type giving an object with a true
-valued property for each string literal type in K
. (You could also use the Record
utility type to give the equivalent Record<K, true>
). Since {}
is not a valid value of this type, you'll need a type assertion 告诉编译器将 obj
视为类型 { [P in K]: true }
.
然后当你创建 myArray
时,编译器的默认行为是将其类型扩展为 Array<{key: string}>
,完全忘记字符串文字类型 "a"
、"b"
,以及 "c"
。为防止这种情况,您可以使用 const
assertion:
let myArray = [{ key: 'a' }, { key: 'b' }, { key: 'c' }] as const;
/* let myArray: readonly [{
readonly key: "a";
}, {
readonly key: "b";
}, {
readonly key: "c";
}] */
注意 const
断言如何使 myArray
成为 readonly
数组,这就是放宽函数输入类型的原因。现在编译器已经足够了解 myArray
,让我们调用 objectFromArray()
:
let myObj = objectFromArray(myArray);
/* let myObj: {
a: true;
b: true;
c: true;
} */
成功!根据需要,myObj
已知具有 a
、b
和 c
类型的 true
属性。