英文:
Reusing function parameter in TypeScript
问题
这需要一些解释。
我有一个名为Dependency
的类,它持有泛型类型T
的值并提供一些辅助方法(在这里并不是特别相关):
class Dependency<T> {
value: T
...
}
我试图编写另一个类,名为Derivative
,它接受依赖项的列表和一个derive
函数,用于生成一些其他值:
type DependencyArray = Array<Dependency<any>>
type DeriveFunc<T, D extends DependencyArray = DependencyArray> = (...deps: D) => Promise<T>
class Derivative<T, D extends DependencyArray = DependencyArray> {
value: T
constructor(
dependencies: D,
derive: DeriveFunc<T, D>,
) { ... }
}
这里有一个关键点 - 我想限制derive
函数只接受由Derivative
构造函数的第一个参数提供的依赖项。例如:
const depA = new Dependency<string>()
const depB = new Dependency<boolean>()
// 好:这个能够编译通过
const new Derivative<string>([depA, depB], async ([a, b]) => `${a}-${b}`)
// 好:这两个编译失败,因为数组的长度不同
// TS2345: Source has 2 element(s) but target allows only 1.
const new Derivative<string>([depA, depB], async ([a]) => `${a}`)
const new Derivative<string>([depA], async ([a, b]) => `${a}`)
// 不好:在这个例子中,`derive`函数不了解依赖项数组中包含的具体类型,因此将它合并到Dependency<string | boolean>[]中
// TS2339: Property 'length' does not exist on type 'boolean | string'.
// Property 'length' does not exist on type 'false'.
const new Derivative<string>([depA, depB], async ([a, b]) => `${a.length}-${b}`)
是否有一种方法可以精确引用传递给Derivative
构造函数的依赖项?
英文:
This will take a bit to explain.
I have a class called Dependency
, which holds a value of generic type T
and provides some helper methods (not really relevant here):
class Dependency<T> {
value: T
...
}
I'm trying to write another class, Derivative
, that takes a list of dependencies and a derive
function to generate some other value:
type DependencyArray = Array<Dependency<any>>
type DeriveFunc<T, D extends DependencyArray = DependencyArray> = (...deps: D) => Promise<T>
class Derivative<T, D extends DependencyArray = DependencyArray> {
value: T
constructor(
dependencies: D,
derive: DeriveFunc<T, D>,
) { ... }
}
Here's the catch – I want to restrict derive
to only accept dependencies provided by first argument to Derivative
constructor.
For example:
const depA = new Dependency<string>()
const depB = new Dependency<boolean>()
// Good: this one compiles
const new Derivative<string>([depA, depB], async ([a, b]) => `${a}-${b}`)
// Good: these two fail to compile, since arrays aren't the same length
// TS2345: Source has 2 element(s) but target allows only 1.
const new Derivative<string>([depA, depB], async ([a]) => `${a}`)
const new Derivative<string>([depA], async ([a, b]) => `${a}`)
// Bad: in this one, `derive` function doesn't understand which types are in dependency array, so it merges it to Dependency<string | boolean>[]
// TS2339: Property 'length' does not exist on type 'boolean | string'.
// Property 'length' does not exist on type 'false'.
const new Derivative<string>([depA, depB], async ([a, b]) => `${a.length}-${b}`)
Is there a way to reference exactly the dependencies that were passed to Derivative
constructor?
答案1
得分: 1
当前,TypeScript 不支持您尝试的操作,因为数组字面量的类型([1, 5, true, null]
)不被隐式转化为元组类型([ number, number, boolean, null]
),而是转化为数组类型((number | boolean | null)[]
)。不幸的是,您无法改变这一点。您可以查看一个相关的 问题,它描述了您尝试的操作。
不管怎样,您可以使用扩展语法代替:
class Derivative<T, D extends DependencyArray = DependencyArray> {
value: T
constructor(
derive: DeriveFunc<T, D>,
...dependencies: D
) { ... }
}
这样,参数类型将被正确隐式推断。不幸的是,没有其他解决方法,如果您想使用数组,您没有特别的选择。
英文:
Currently, TypeScript doesn't support what you're trying to do, since the types of array literals ([1, 5, true, null]
) aren't imlied to tuples ([ number, number, boolean, null]
), but instead to an array type ((number | boolean | null)[]
). Unfortunately, there's nothing you can do about it. There's an issue you can take a look at, it describes exactly what you're trying to do.
Regardless, you can use the spread syntax instead:
class Derivative<T, D extends DependencyArray = DependencyArray> {
value: T
constructor(
derive: DeriveFunc<T, D>,
...dependencies: D
) { ... }
}
In this way, argument types will get implied correctly. Unfortunately, there are no other workarounds, and if you want to use an array, you don't have a particular choice.
答案2
得分: 0
只有翻译部分,不包括代码:
It turns out using objects instead of arrays works just fine.
I had to switch to something like that:
类型 DependencyMap = { [key: string]: Dependency
类型 DeriveFunc<T, D> = (deps: D) => Promise
const new Derivative${depA.length}-${depB}
)
英文:
It turns out using objects instead of arrays works just fine.
I had to switch to something like that:
type DependencyMap = { [key: string]: Dependency<any> }
type DeriveFunc<T, D> = (deps: D) => Promise<T>
const new Derivative<string>({ depA, depB }, async ({ depA, depB }) => `${depA.length}-${depB}`)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论