大佬教程收集整理的这篇文章主要介绍了如何在 Typescript 中输入匹配/折叠功能,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我尝试了一段时间来为匹配/折叠函数编写正确的类型。希望有人能帮助我了解我做错了什么。
该函数应该是通用的,但请考虑以下联合类型作为示例。
class Square {
type = "Square" as const
constructor(public sIDe: number) {}
}
class Circle {
type = "Circle" as const
constructor(public radius: number) {}
}
class Rectangle {
type = "Rectangle" as const
constructor(public wIDth: number,public height: number) {}
}
type Shape = Square | Circle | Rectangle
我希望有一个匹配函数,这样我就可以处理所有选项并为此具有类型安全性。它有点适用于这个解决方案。
type XMap<T,Key extends keyof T> = { [K in T[Key]]: T extends { type: K } ? T : never }
type XPattern<T,Key extends keyof T,R> = { [K in keyof XMap<T,Key>]: (shape: XMap<T,Key>[K]) => R }
function matcher<T,R>(key: Key,pattern: XPattern<T,Key,R>): (shape: T) => R {
return shape => pattern[shape[key]](shape as any)
}
const area = matcher<Shape,'type',number>('type',{
Square: square => square.sIDe * square.sIDe,Circle: circle => circle.radius * circle.radius * Math.PI,Rectangle: rect => rect.height * rect.wIDth
})
const shapes = [new Circle(4.0),new Square(5.0),new Rectangle(6.0,7.0)]
console.log(`Areas: ${shapes.map(area)}`)
Playground Link
正如你在这个 Playground 中看到的,它仍然会给出错误,但不知何故向我展示了匹配器中的正确类型。不知道如何解决这个问题。
感谢您的时间和帮助。
这是让它工作的一种方法。请注意,为了匹配目的,我必须使用不同的类型:
type Shape = Square | Circle | Rectangle
/**
* Given a type,a key on that type,and a potential value,* return if type is an object that extends { [key]: value }
*
* Since union types diStribute over conditionals (it tries one at a timE),* this lets us start out with Shape and end up with a single of the three
*/
type XMatching<T,TKey extends keyof T,TValue> = T extends { [P in TKey]: TValue }
? T
: never
type Test01 = XMatching<Shape,'type','Circle'> // Circle
type Test02 = XMatching<Shape,'Square' | 'Circle'> // Square | Circle
type Test03 = XMatching<Shape,'type2','Square'> // ERR since `type2` is not a shared field
type Test04 = XMatching<Shape,'Ellipse'> // never
/**
* Given a type T,a key on that type TK,and another arbitrary type TR,* if type.key extends String (and therefore can be used as a key itself)
* generate a map from all possible values of type.key to
* functions that take in the particular object with that particular value of type.key,e.g.
*
* 'Circle' -> Circle
* 'Square' -> Square
*
* and returns the arbitrary type TR.
*
* Otherwise,return never.
*
* (there are certainly ways to write this without the conditional)
*/
type XPattern<T,TR> = T[TKey] extends String
? { [P in T[TKey]]: (matched: XMatching<T,TKey,P>) => TR }
: never
function matcher<T,TR>(key: TKey,pattern: XPattern<T,TR>): (matched: T) => TR {
return shape => pattern[shape[key]](shapE)
}
const shapes = [new Circle(4.0),new Square(5.0),new Rectangle(6.0,7.0)]
const area = matcher<Shape,number>('type',{
Square: square => square.side * square.side,Circle: circle => circle.radius * circle.radius * Math.PI,Rectangle: rect => rect.height * rect.width
}) // OK!
const badArea01 = matcher<Shape,Rectangle: rect => rect.height * rect.width,Ellipse: ellipse => ellipse.radiusA * ellipse.radiusB * Math.PI
}) // ERR since Ellipse has no match
const badArea02 = matcher<Shape,Rectangle: rect => "real big!"
}) // ERR since returns a String,not a number
以上是大佬教程为你收集整理的如何在 Typescript 中输入匹配/折叠功能全部内容,希望文章能够帮你解决如何在 Typescript 中输入匹配/折叠功能所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。