首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >它可以是强类型的吗?

它可以是强类型的吗?
EN

Stack Overflow用户
提问于 2019-01-21 17:48:05
回答 1查看 41关注 0票数 1

我正在尝试在Typescript中实现一种伪模式匹配,利用它们对区分联合的支持,利用匹配函数和表示匹配表达式分支的对象。

以下是我希望能够使用的场景:

代码语言:javascript
运行
AI代码解释
复制
type Shape = 
    | { kind: 'Circle', radius: number }
    | { kind: 'Rectangle', height: number, width: number }

function printShape(s: Shape) {
    return document.write(
        match(s, {
        'Circle': c => `Circle(${c.radius})`,
        'Rectangle': r => `Rectangle(${r.width} x ${r.height})`
    }));
}

我现在尝试定义match函数,如下所示:

代码语言:javascript
运行
AI代码解释
复制
function match<T extends { kind: V }, V extends string, R>(
    x: T, branches: { [P in T['kind']]: (arg: T & { 'kind': P }) => R }) {

    return branches[x.kind](x);
}

这很接近,但不幸的是,这并不能很好地工作;虽然我已经成功地让编译器抱怨给定匹配的完整性,但分支函数的参数类型不是很好:参数cr的类型为any

我可以使用kind作为硬编码的鉴别器,但是我通常不理解如何在Typescript中过滤出泛型类型联合的可能性。例如,我将我的练习提炼为尝试编写以下代码:

代码语言:javascript
运行
AI代码解释
复制
type Where<T, K extends keyof T, V extends T[K]> = ???

我的类型约束是正确的,因为当我编写以下代码时,我从编译器获得了关于类型和文字的正确验证:

代码语言:javascript
运行
AI代码解释
复制
type Circle = Where<Shape, 'kind', 'Circle'>

但是我不明白我可以在类型表达式的右边写什么来返回:

代码语言:javascript
运行
AI代码解释
复制
{ kind: 'Circle', radius: number }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-01-21 18:01:53

要从联合中提取特定类型,可以使用Extract条件类型。这将提取作为第二个参数的子类的所有联合成员。因此,where类型将如下所示:

代码语言:javascript
运行
AI代码解释
复制
type Where<T, K extends keyof T, V extends T[K]> = Extract<T, Record<K, V>>
type C = Where<Shape, 'kind', 'Circle'> //{ kind: 'Circle', radius: number }

如果使用返回函数的函数,则可以获得该函数的完整类型。第一个调用设置T,第二个调用可以使用类型信息来完整地键入参数:

代码语言:javascript
运行
AI代码解释
复制
type Shape =
  | { kind: 'Circle', radius: number }
  | { kind: 'Rectangle', height: number, width: number }

function printShape(s: Shape) {
  var r = match(s)({
    'Circle': c => `Circle(${c.radius})`,
    'Rectangle': r => `Rectangle(${r.width} x ${r.height})`
  }) // r is string
  return document.write(r);
}


function match<T extends { kind: V }, V extends string>(x: T) {
  return function <R>(branches: { [P in T['kind']]: (arg: Extract<T, { 'kind': P }>) => R }) {

    return branches[x.kind](x as any);
  }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54295322

复制
相关文章

相似问题

领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档