- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有一个元组,其中类型相互关联。在我的例子中,它是一个提取函数,提取一个值,该值又用作另一个函数的输入。
从概念上讲,我正在寻找的是这样的东西,但这不会编译:
const a: <T>[(v:any) => T, (t:T) => void] = [ ... ]
用例是这样的。我有一个 any
类型的传入 RPC 消息,以及一个具有众所周知参数类型的 API。我想构建一个采用两个参数的“布线计划”,一个提取器函数和相应的 API 函数。
export interface API = {
saveModel : (model:Model) => Promise<boolean>,
getModel : (modelID:string) => Promise<Model>,
}
const api: API = { ... }
// this is the tuple type where i'd like to define that
// there's a relation between the second and third member
// of the tuple.
type WirePlan = [[string, (msg:any) => T, (t:T) => Promise<any>]]
const wirePlan: WirePlan = [[
['saveModel', (msg:any) => <Model>msg.model , api.saveModel],
['getModel' , (msg:any) => <string>msg.modelID, api.getModel],
]
const handleMessage = (msg) => {
const handler = wirePlan.find((w) => w[0] === msg.name)
const extractedValue = handler[1](msg)
return handler[2](extractedValue)
}
我可以通过其他方式解决这个问题,我只是突然想到,关于元组可能有些我不理解的地方。
最佳答案
Conceptually what I'm looking for is something like this, but this doesn't compile:
const a: <T>[(v:any) => T, (t:T) => void] = [ ... ]
也就是说,事实上,您想要的相反。借助函数类型的直觉,a: <T>(t: T) => T
意味着您拥有适用于所有 类型的函数。这是一个通用量词:a
的实现不知道什么T
是; a
的用户可以设置T
到他们想要的任何东西。对元组执行此操作将是灾难性的,因为内部函数需要输出 T
的值。不管怎样T
是,因此他们唯一能做的就是错误输出/永远循环/以某种方式处于底部(他们必须返回 never
)。
你想要existential quantification . a: ∃T. [(v:any) => T, (t:T) => void]
意味着 a
有某种类型 T
与之相关。 a
的执行知道它是什么,可以用它做任何想做的事,但是 a
的用户现在对此一无所知。实际上,与通用量化相比,它颠倒了角色。 TypeScript doesn't have support for existential types (甚至不是像 Java 的通配符那样的 super 基本形式),但它 can be simulated :
type WirePlanEntry = <R>(user: <T>(name: string, reader: (msg: any) => T, action: (t: T) => Promise<any>)) => R
type WirePlan = WirePlanEntry[]
是的,那是一口。可以分解为:
// Use universal quantification for the base type
type WirePlanEntry<T> = [string, (msg: any) => T, (t: T) => Promise<any>]
// A WirePlanEntryConsumer<R> takes WirePlanEntry<T> for any T, and outputs R
type WirePlanEntryConsumer<R> = <T>(plan: WirePlanEntry<T>) => R
// This consumer consumer consumes a consumer by giving it a `WirePlanEntry<T>`
// The type of an `EWirePlanEntry` doesn't give away what that `T` is, so now we have
// a `WirePlanEntry` of some unknown type `T` being passed to a consumer.
// This is the essence of existential quantification.
type EWirePlanEntry = <R>(consumer: WirePlanEntryConsumer<R>) => R
// this is an application of the fact that the statement
// "there exists a T for which the statement P(T) is true"
// implies that
// "not for every T is the statement P(T) false"
// Convert one way
function existentialize<T>(e: WirePlanEntry<T>): EWirePlanEntry {
return <R>(consumer: WirePlanEntryConsumer<R>) => consumer(e)
}
// Convert the other way
function lift<R>(consumer: WirePlanEntryConsumer<R>): (e: EWirePlanEntry) => R {
return (plan: EWirePlanEntry) => plan(consumer)
}
消费 EWirePlanEntry
看起来像
plan(<T>(eT: WirePlanEntry<T>) => ...)
// without types
plan(eT => ...)
但是如果你只有这样的消费者
function consume<T>(plan: WirePlanEntry<T>): R // R is not a function of T
你会像这样使用它们
plan(consume) // Backwards!
lift(consume)(plan) // Forwards!
不过,现在您可以拥有制作人了。已经编写了最简单的此类生产者:existentialize
.
这是您的其余代码:
type WirePlan = EWirePlanEntry[]
const wirePlan: WirePlan = [
existentialize(['saveModel', (msg:any) => <Model>msg.model , api.saveModel]),
existentialize(['getModel' , (msg:any) => <string>msg.modelID, api.getModel ]),
]
const handleMessage = (msg: any) => {
let entry = wirePlan.find(lift((w) => w[0] === msg.name))
if(entry) {
entry(handler => {
const extractedValue = handler[1](msg)
return handler[2](extractedValue)
})
}
}
关于typescript - 如何键入参数化元组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46185023/
我已经写了并且 npm 发布了这个:https://github.com/justin-calleja/pkg-dependents 现在我正在用 Typescript 编写这个包:https://g
我有一个函数,我想在 TypeScript 中模拟它以进行测试。在我的测试中,我只关心 json和 status .但是,当使用 Jest 的 jest.spyOn 时我的模拟函数的类型设置为返回 h
我正在使用一个库 (Axios),它的包中包含 Typescript 声明。 我想声明一个将 AxiosResponse(在库的 .d.ts 文件中声明)作为参数的函数。我有以下内容: functio
我是 Typescript 的新手。我想使用 将一个 Typescript 文件加载到另一个 Typescript 文件中标签。 我做了一些事情,但它不起作用!请帮助我。 first.ts: imp
为什么我会收到下面屏幕截图中显示的错误? Atom 说我的 tsconfig.json“项目文件包含无效选项”用于 allowJs、buildOnSave 和 compileOnSave。 但是应该允
所以我正在创建一个 TypeScript 库,我可以轻松地将所有生成的 JS 文件编译成一个文件。有没有办法将所有 .ts 和 .d.ts 编译成一个 .ts 文件? 除了支持 JS 的版本(较少的智
Microsoft Research 提供了一种名为Safer TypeScript 的新 TypeScript 编译器变体: http://research.microsoft.com/en-us/
我需要这个来在单个文件中分发 TypeScript 中的库。有没有办法将多个 typescript 文件合并到(一个js文件+一个 typescript 定义)文件中? 最佳答案 要创建一个库,您可以
用例:我想知道一个函数在 typescript 中执行需要多少时间。我想为此目的使用装饰器。我希望装饰器应该返回时间以便(我可以进一步使用它),而不仅仅是打印它。 例如: export functio
我想检查一个类型是否可以为 null,以及它是否具有值的条件类型。 我尝试实现 type IsNullable = T extends null ? true : false; 但是好像不行 type
我的问题是基于这个 question and answer 假设我们有下一个代码: const myFn = (p: { a: (n: number) => T, b: (o: T) => v
我知道双重否定前缀,我知道 TypeScript 的单后缀(非空断言)。 但是这个双后缀感叹号是什么? /.*验证码为(\d{6}).*/.exec(email.body!!)!![1] 取自here
我正在使用以下文件结构在 Webstorm 中开发一个项目 | src | ... | many files | types | SomeInterface |
在 TypeScript 类中,可以为属性声明类型,例如: class className { property: string; }; 如何在对象字面量中声明属性的类型? 我试过下面的代码,但它
我正在寻找一种在不丢失推断类型信息的情况下将 TypeScript 中的文字值限制为特定类型的好方法。 让我们考虑一个类型Named,它保证有一个名字。 type Named = { name:
在 TypeScript 中,我想创建一个联合类型来表示属于一个或多个不同类型的值,类似于 oneOf在 OpenAPI或 JSON Schema .根据a previous answer on a
type Func = (foo:string) => void // function expression const myFunctionExpression:Func = function(f
假设我有一个联合类型,我正在使用类似 reducer 的 API 调用模式,看起来像这样: type Action = { request: { action: "create
我在 typescript 中有以下去抖功能: export function debounce( callback: (...args: any[]) => void, wait: numb
在 Vue3 的 defineComponent 函数中,第一个泛型参数是 Props,所以我在这里使用 Typescript 接口(interface)提供我的 props 类型。喜欢: expor
我是一名优秀的程序员,十分优秀!