- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在我这里的这段代码中:
type GETR<a extends string, b extends string> = [a,b]
interface Options<A extends string, B extends string> {
bar: GETR<A,B>
}
function foo<A extends string, B extends string, C extends Options<A, B>>(r: C) {
return r
}
const bar:GETR<"foo", "bar"> = null as any as GETR<"foo", "bar">
const x = foo({ bar })
没有类型错误。 See it here
现在,如果我只更改 GETR 的类型,从 [a,b]
到 (k:a) => b
没有其他更改。然后不再推断通用类型参数,我有一个类型错误:
type GETR<a extends string, b extends string> = (k:a) => b
interface Options<A extends string, B extends string> {
bar: GETR<A,B>
}
function foo<A extends string, B extends string, C extends Options<A, B>>(r: C) {
return r
}
const bar:GETR<"foo", "bar"> = null as any as GETR<"foo", "bar">
const x = foo({ bar })
有类型错误。 See it here
我想了解为什么,最好的解决办法是什么?
最佳答案
我相信这是因为逆变。但是,我不是 100% 确定,因为它也可能是不变的。有一个简单的解决方法,只需去掉 C
泛型参数:
type Fn<Arg extends string, Return extends string> = (k: Arg) => Return
interface Options<Arg extends string, Return extends string> {
prop: Fn<Arg, Return>
}
function foo<
Arg extends string,
Return extends string,
>(r: Options<Arg, Return>) {
return r
}
declare const prop: Fn<"foo", "bar">
const x = foo({ prop }) // ok
考虑这个小例子:
declare let stringString: Options<string, string>
declare let fooBar: Options<'foo', 'bar'>
stringString = fooBar // error
fooBar = stringString // error
您可能已经注意到:stringString
和 fooBar
不能相互赋值。
问题出在 Arg
泛型类型中(在您的示例中是 a
)。如果您去掉 Arg
(a
),您的示例将编译:
type Fn<Return extends string> = () => Return
type Options<Return extends string> = {
prop: Fn<Return>
}
function foo<
Return extends string,
C extends Options<Return>
>(r: C) {
return r
}
declare const prop: Fn<"bar">
const x = foo({ prop }) // no error
它可以编译,因为 Return
处于协变位置。
让我们尝试添加 Arg
但去掉 Return
:
type Fn<Arg extends string> = (arg: Arg) => void
type Options<Arg extends string> = {
prop: Fn<Arg>
}
function foo<
Arg extends string,
C extends Options<Arg>
>(r: C) {
return r
}
declare const prop: Fn<"foo">
const x = foo({ prop }) // still error
declare let stringPrimitive: string;
declare let fooBarPrimitive: 'bar'
stringPrimitive = fooBarPrimitive // ok
fooBarPrimitive = stringPrimitive // error
declare let stringString: Options<string>
declare let fooBar: Options<'bar'>
stringString = fooBar // error
fooBar = stringString // ok
还是有错误。请检查 stringPrimitive
、fooBarPrimitive
、stringString
和 fooBar
的可分配性。
在第一个示例中,fooBarPrimitive
文字类型可分配给字符串,这是预期的。但是,在第二个示例中,由于逆变
,fooBar
不再可分配给stringString
。函数参数处于逆变位置。
让我们尝试添加 Return
泛型(在您的示例中是 b
):
type Fn<Arg extends string, Return extends string> = (arg: Arg) => Return
type Options<Arg extends string, Return extends string> = {
prop: Fn<Arg, Return>
}
function foo<
Arg extends string,
Return extends string,
C extends Options<Arg, Return>
>(r: C) {
return r
}
declare const prop: Fn<"foo", 'bar'>
const x = foo({ prop }) // still error
declare let stringString: Options<string, string>
declare let fooBar: Options<'foo', 'bar'>
stringString = fooBar // error
fooBar = stringString // error
请检查 stringString
和 fooBar
的可分配性,它们根本无法相互分配。在这两种情况下,您都会遇到错误。
据我了解,添加 C
泛型会触发 Arg
泛型的逆变
行为。
这不是我第一次遇到这种行为。
考虑这个例子,但请关闭 strictFunctionTypes
标志:
type Animal = { tag: 'animal' }
type Dog = Animal & { bark: true }
type Cat = Animal & { meow: true }
declare let animal: (x: Animal) => void;
declare let dog: (x: Dog) => void;
declare let cat: (x: Cat) => void;
animal = dog; // ok without strictFunctionTypes and error with
dog = animal; // should be ok
dog = cat; // should be error
dog
可以分配给 animal
但不应该。
现在,尝试将泛型添加到 animal
函数:
type Animal = { tag: 'animal' }
type Dog = Animal & { bark: true }
// generic is here
declare let animal: <T extends Animal>(x: T) => void;
declare let dog: (x: Dog) => void;
animal = dog; // error even without strictFunctionTypes
现在,即使没有 strictFunctionTypes
标志,dog
也不能分配给 animal
。我没有在文档中找到对此行为的解释。
见相应文章here
请查看this answer如果您对 *-方差主题感兴趣。
附言如果有人证实或批评我的想法,我会很高兴,我已经尽力了
关于typescript - 当参数是函数时不推断通用类型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73733474/
当使用模板模板参数时,我如何推断或删除模板模板的模板类型? 考虑以下 SSCCE: #include #include #include using namespace std; templat
假设我有一些特质: trait A[T] { def foo: T } 一个扩展它的类: class B[T](t: T) extends A[T] { def foo = t } 以及父特征的子特征
一边玩-rectypes在某些时候选择 OCaml 我只是迷路了。 这个表达式几乎可以打字: # fun x -> x x;; - : ('a -> 'b as 'a) -> 'b = 但是这里 O
我正在编写一个类似 CRUD 的应用程序,并且通过主键进行大量查找(主键可以有不同的类型)。所以我定义了以下类型类: {-# LANGUAGE MultiParamTypeClasses #-} cl
我已经创建了关系 A 'is functional parent of' B并定义 'has functional parent'作为 'is functional parent of' 的倒数. '
给定一个使用 Kotlin 版本 1.3.61 和 JOOQ 版本 3.13.1 的系统,这样的方法会构建 union正常查询: val selectCommonPart = coalesce
考虑以下错误代码: fun x = if (null x) then 0 else (take 50 x) : (fun (drop 50 x)) 我注意到,我可以毫无问题地将它加载到
给定一个具有以下类型的函数 a: a::x -> Bool 和以下类型的另一个函数 b: b::Bool -> y 我正在尝试找出推断以下函数类型的步骤: c =\d -> d a b 有人可以帮助解
我正在尝试使用 Infer 工具来分析我的应用代码。我关注了these steps每次我尝试运行 infer -- gradle build 时,我都会收到以下错误: infer -- gradle
所以我制作了这个模板来定义内联仿函数: template struct AsFunctor { template std::invoke_result_t operator()(A
是否可以推断 CRTP 基类中模板化成员函数的返回类型? 虽然推断参数类型效果很好,但它因返回类型而失败。考虑以下示例。 #include template struct base { tem
使用 Series.interpolate 很容易在 Pandas.DataFrame 中插入值,如何进行外推? 例如,给定一个如图所示的 DataFrame,我们如何将它外推 14 个月到 2014
我想知道为什么这不起作用(缺少参数类型)? Seq(1,2,3).toSet.map(_ + 1) 但这确实: val foo = Seq(1,2,3).toSet foo.map(_ + 1)
我没有必要使用 SQLite3 shell 工具来维护一个小型数据库。我正在使用 -header -ascii标志,尽管据我所知,这适用于任何输出选择。我正在寻找一种方法来避免对返回的任何一个值的类型
我有以下组件 type PropTypes = { items: T[], header: (item: T) => React.Element, body: (item: T) => R
我想在 Eclipse/JSDT 中指定实例变量的类型,如下例所示: /** * @constructor */ function A() { /** @type Node */
我正在用 Python 编写一个方法,它看起来像这样: def rgb_to_grayscale(image): print(image.shape) pass 此处预期的类型是 nu
我有一个 my_values 数组,我正在尝试为其推断 true_values 数组中最接近、较小的值。使用下面的 find_nearest 函数并不能完成我想要的。我如何追加它以找到最近的、较小的值
在下面的代码中: template int b(int q, const std::array& types) { int r = q; for (int t : types)
在 Pandas DataFrame 中插入 NaN 单元非常容易: In [98]: df Out[98]: neg neu pos av
我是一名优秀的程序员,十分优秀!