Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Typescript 4.0+是否能够使用映射的变量元组类型执行函数?_Typescript_Typescript Typings_Typescript4.0 - Fatal编程技术网

Typescript 4.0+是否能够使用映射的变量元组类型执行函数?

Typescript 4.0+是否能够使用映射的变量元组类型执行函数?,typescript,typescript-typings,typescript4.0,Typescript,Typescript Typings,Typescript4.0,例如,假设我有一个简单的函数,它将可变数量的事物映射到像{a:value}这样的对象数组 const mapToMyInterface=…things=>things.mapthing=>{a:thing}; 中的Typescript尚无法推断此函数结果的强类型: 常量mapToMyInterface=maptointerface 1,3,2';//推断类型{a:any}[] 首先,我定义了一个类型来描述映射到可观察对象的数组: 类型MapToMyInterface={ [K in keyof

例如,假设我有一个简单的函数,它将可变数量的事物映射到像{a:value}这样的对象数组

const mapToMyInterface=…things=>things.mapthing=>{a:thing}; 中的Typescript尚无法推断此函数结果的强类型:

常量mapToMyInterface=maptointerface 1,3,2';//推断类型{a:any}[] 首先,我定义了一个类型来描述映射到可观察对象的数组:

类型MapToMyInterface={ [K in keyof T]:T[K]扩展数组{a:U}:{a:T[K]} } 现在我更新我的函数:

const mapToMyInterface=…things:T:mapToMyInterface=>things.mapthing=>{a:thing}; 到目前为止,Typescript并不高兴。函数的返回表达式高亮显示,错误为TS2322:类型“{a:any;}[]”不可分配给类型“MapToMyInterface”

显然,需要在映射函数中显式地键入参数。但是我不知道怎么说第n种类型,这正是我需要的

也就是说,既不将事物标记为T[数字],也不做以下工作:

常量mapToMyInterface=…things:T:mapToMyInterface=>things.mapthing:T[K]=>of things; 这可以在Typescript中工作吗

在@jcalz的回答后编辑: 为了子孙后代,我想发布我问题的原始动机,以及从@jcalz的答案中得到的解决方案

我试图用LatestFrom包装一个RxJs操作符,以便在传递函数结果时,对传递到其中的观察值进行惰性评估。该函数在某个地方启动正在进行的订阅,如NgRx中的store.select

我能够成功地断言返回值,如下所示:

导出常量lazyWithLatestFrom=o:=>[…T]=> concatMapvalue=>ofvalue.pipewithLatestFrom…o作为运算符函数< v [V,{[i in keyof T]:TypeOfObservable}] >;
您可以输入任意数量的不同类型的参数,并以相同的顺序返回这些类型的可观察对象数组吗?不可以。不能基于特定的数字键映射类型

你能输入那些相同的任意参数,并用这些类型的并集返回一个观察值数组吗?对


您可以输入任意数量的不同类型的参数,并以相同的顺序返回这些类型的可观察对象数组吗?不可以。不能基于特定的数字键映射类型

你能输入那些相同的任意参数,并用这些类型的并集返回一个观察值数组吗?对


假设您有一个通用函数wrap,它接受类型为T的值并返回类型为{a:T}的值,如您的示例所示:

function wrap<T>(x: T) {
    return ({ a: x });
}
这完全忘记了进入的各个类型及其顺序,而您只需要一个{a:any}数组。这是事实,但不是很有用:

const weak = mapWrapWeaklyTyped(1, "two", new Date());
try {
    weak[2].a.toUpperCase(); // no error at compile time, but breaks at runtime
} catch (e) {
    console.log(e); // weak[2].prop.toUpperCase is not a function 
}
该死的,编译器没有捕捉到2引用数组的第三个元素这一事实,该元素是包装日期,而不是包装字符串。我不得不等到运行时才能看到问题

如果查看for Array.prototype.map,您将了解发生这种情况的原因:

interface Array<T> {
  map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];
}
我们在这里所做的只是迭代T数组的每个数字索引K,并在该索引处获取T[K]元素,并将其映射到{a:T[K]}

请注意,因为标准库的map类型没有预料到这个特定的泛型映射函数,所以必须使用类型检查。如果您只关心编译器在没有类型断言的情况下无法验证这一点,那么这实际上是在TypeScript中没有更高级类型的情况下所能做的最好的事情

您可以在与前面相同的示例中进行测试:

const strong = mapWrapStronglyTyped(1, "two", new Date());
try {
    strong[2].a.toUpperCase(); // compiler error, Property 'toUpperCase' does not exist on type 'Date'
} catch (e) {
    console.log(e); //  strong[2].prop.toUpperCase is not a function 
}
// oops, I meant to do this instead!
console.log(strong[1].a.toUpperCase()); // TWO
现在编译器发现了这个错误,并告诉我Date对象没有toUpperCase方法。万岁

你的地图版本

type MapToMyInterface<T extends any[]> = {
  [K in keyof T]: T[K] extends Array<infer U> ? { a: U } : { a: T[K] }
}
有点奇怪,因为你做了两次映射;除非传入数组的数组,否则没有理由检查T[K]本身是否是数组。T是数组,K是数组的索引。所以我会说只要返回{a:T[K]},除非我错过了一些重要的东西


假设您有一个通用函数wrap,它接受类型为T的值并返回类型为{a:T}的值,如您的示例所示:

function wrap<T>(x: T) {
    return ({ a: x });
}
这完全忘记了进入的各个类型及其顺序,而您只需要一个{a:any}数组。这是事实,但不是很有用:

const weak = mapWrapWeaklyTyped(1, "two", new Date());
try {
    weak[2].a.toUpperCase(); // no error at compile time, but breaks at runtime
} catch (e) {
    console.log(e); // weak[2].prop.toUpperCase is not a function 
}
该死的,编译器没有捕捉到2引用数组的第三个元素这一事实,该元素是包装日期,而不是包装字符串。我不得不等到运行时才能看到问题

如果查看for Array.prototype.map,您将了解发生这种情况的原因:

interface Array<T> {
  map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];
}
我们在这里所做的只是迭代T数组的每个数字索引K,并在该索引处获取T[K]元素,并将其映射到{a:T[K]}

注t hat因为标准库的映射类型没有预料到这个特定的泛型映射函数,所以必须使用类型检查。如果您只关心编译器在没有类型断言的情况下无法验证这一点,那么这实际上是在TypeScript中没有更高级类型的情况下所能做的最好的事情

您可以在与前面相同的示例中进行测试:

const strong = mapWrapStronglyTyped(1, "two", new Date());
try {
    strong[2].a.toUpperCase(); // compiler error, Property 'toUpperCase' does not exist on type 'Date'
} catch (e) {
    console.log(e); //  strong[2].prop.toUpperCase is not a function 
}
// oops, I meant to do this instead!
console.log(strong[1].a.toUpperCase()); // TWO
现在编译器发现了这个错误,并告诉我Date对象没有toUpperCase方法。万岁

你的地图版本

type MapToMyInterface<T extends any[]> = {
  [K in keyof T]: T[K] extends Array<infer U> ? { a: U } : { a: T[K] }
}
有点奇怪,因为你做了两次映射;除非传入数组的数组,否则没有理由检查T[K]本身是否是数组。T是数组,K是数组的索引。所以我会说只要返回{a:T[K]},除非我错过了一些重要的东西


你能把这里的代码变成一个可以放到独立IDE中的代码吗?现在您使用的是Observable,它依赖于第三方库。如果您的问题依赖于此库,则可能应该将其标记为该库。如果不是,你可能想通过提供一个类似的玩具实现来消除依赖性。也许这就是你想要的?Array.prototype.map的内置类型本身不会执行任何更高阶的操作,但是您当然可以自己为它指定一个适当的映射元组类型。@jcalz它们都来自“rxjs”库,但of似乎返回任何类型,这使得严格的返回类型无效。而且它似乎也被弃用了。@jcalz@Linda Paise我已经更新了我的问题,使用了一个虚构的对象而不是可观察的对象,以使问题的内容清晰明了。你能把这里的代码变成一个可以放入独立IDE中的代码来演示这个问题吗?现在您使用的是Observable,它依赖于第三方库。如果您的问题依赖于此库,则可能应该将其标记为该库。如果不是,你可能想通过提供一个类似的玩具实现来消除依赖性。也许这就是你想要的?Array.prototype.map的内置类型本身不会执行任何更高阶的操作,但是您当然可以自己为它指定一个适当的映射元组类型。@jcalz它们都来自“rxjs”库,但of似乎返回任何类型,这使得严格的返回类型无效。而且它似乎已经被弃用了。@jcalz@Linda Paise我已经更新了我的问题,用一个虚构的对象而不是可观察的对象来让我的问题的内容变得清晰。是的,这就是我担心的。这就是为什么一些RxJs操作符仍然有一堆函数声明来为前六个参数提供强类型。我试图编写一个用LatestFrom包装的操作符,但我必须遵循RxJs今天所做的相同类型来实现我想要的,我想。我可能说得太快了:我会编辑我的答案,但我不明白你想用t[K]数组做什么?{a:U}:{a:T[K]}因为您的实际函数没有检查每个条目是否为数组,所以它会返回{a:T[K]}。问题不是生成一个将每个元素从原始元素转换的类型-我的解决方案和您链接的问题答案中的解决方案都实现了这一点。我的问题是Typescript不相信为mapToMyInterface编写的函数符合返回类型。是的,这就是我担心的。这就是为什么一些RxJs操作符仍然有一堆函数声明来为前六个参数提供强类型。我试图编写一个用LatestFrom包装的操作符,但我必须遵循RxJs今天所做的相同类型来实现我想要的,我想。我可能说得太快了:我会编辑我的答案,但我不明白你想用t[K]数组做什么?{a:U}:{a:T[K]}因为您的实际函数没有检查每个条目是否为数组,所以它会返回{a:T[K]}。问题不是生成一个将每个元素从原始元素转换的类型-我的解决方案和您链接的问题答案中的解决方案都实现了这一点。我的问题是Typescript不相信为mapToMyInterface编写的函数符合返回类型。