TypeScript:根据类型返回不同的函数
我想要实现的是一个钩子,它返回一个我可以调用的函数。
type TypeName = 'circle' | 'square';
interface Circle {
type: TypeName;
radius: number;
}
interface Square {
type: TypeName;
length: number;
}
type Shape = Circle | Square;
const useShapeFilter = (shape: Shape) => {
const circleFilter = (circle: Circle) => (circle.radius < 5);
const squareFilter = (square: Square) => (square.length < 5);
return {applyFilter: shape.type === 'circle' ? circleFilter : shape.type === 'square' ? squareFilter : undefined}
}
export const ShapeComponent = () => {
const shape: Circle = {type: 'circle', radius: 10}
const {applyFilter} = useShapeFilter(shape);
return <div>Less than 5 : {applyFilter && applyFilter(shape)}</div>
}
但上面的代码将在 applyFilter(shape)
区域返回 TypeScript 错误: Argument of type 'Circle' is not allocate to argument of type 'Circle &正方形'。 “Circle”类型中缺少属性“length”,但“Square”类型中需要属性“length”。
。
最后,我不得不改变实现并断言数据:
const useShapeFilter = (shape: Shape) => {
const circleFilter = (circle: Circle) => (circle.radius < 5);
const squareFilter = (square: Square) => (square.length < 5);
if (shape.type === 'circle') {
return circleFilter(shape as Circle)
}
if (shape.type === 'square') {
return squareFilter(shape as Square)
}
return undefined;
}
export const AnimalPage = () => {
const shape: Circle = {type: 'circle', radius: 10}
const filtered = useShapeFilter(shape);
return <div>Less than 5 : {filtered}</div>
}
但我仍然想知道如何实现我的初衷。
What I want to achieve is a hook that returns me a function that I can call.
type TypeName = 'circle' | 'square';
interface Circle {
type: TypeName;
radius: number;
}
interface Square {
type: TypeName;
length: number;
}
type Shape = Circle | Square;
const useShapeFilter = (shape: Shape) => {
const circleFilter = (circle: Circle) => (circle.radius < 5);
const squareFilter = (square: Square) => (square.length < 5);
return {applyFilter: shape.type === 'circle' ? circleFilter : shape.type === 'square' ? squareFilter : undefined}
}
export const ShapeComponent = () => {
const shape: Circle = {type: 'circle', radius: 10}
const {applyFilter} = useShapeFilter(shape);
return <div>Less than 5 : {applyFilter && applyFilter(shape)}</div>
}
But the above will return a TypeScript error at the applyFilter(shape)
area: Argument of type 'Circle' is not assignable to parameter of type 'Circle & Square'. Property 'length' is missing in type 'Circle' but required in type 'Square'.
.
In the end, I had to change the implementation and assert the data:
const useShapeFilter = (shape: Shape) => {
const circleFilter = (circle: Circle) => (circle.radius < 5);
const squareFilter = (square: Square) => (square.length < 5);
if (shape.type === 'circle') {
return circleFilter(shape as Circle)
}
if (shape.type === 'square') {
return squareFilter(shape as Square)
}
return undefined;
}
export const AnimalPage = () => {
const shape: Circle = {type: 'circle', radius: 10}
const filtered = useShapeFilter(shape);
return <div>Less than 5 : {filtered}</div>
}
But I'm still wondering how to achieve my original intention.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
由于您返回的函数联合与原始参数没有任何关系,因此打字稿无法真正遵循
shape
实际上适合applyFilter
的事实。一般来说,如果一个变量可以保存两个函数中的任何一个,那么只有使用该变量调用该变量才是安全的,并且参数对于任一潜在的底层函数都有效。为了解决这个问题,我们可以使
useShapeFilter
通用,捕获原始参数,并返回一个与该特定参数兼容的函数:游乐场链接
Since you are returning a union of functions without any relation to the original parameter, typescript can't really follow the fact that
shape
will actually fit intoapplyFilter
. Generally if a variable can hold any one of two functions it is only safe to call the variable with and argument would be valid for EITHER one of the potential underlying functions.To get around this we could make
useShapeFilter
generic, capture the original parameter, and return a function that will be compatible with that specific argument:Playground Link