类型“Observable”'不可分配给类型“Observable

发布于 2025-01-11 04:59:20 字数 1544 浏览 0 评论 0原文

我们正在使用 Knockout.js (v3.5.0) 及其 TypeScript 定义。在 TypeScript 4.6.2 之前它们都工作正常。然而,问题似乎比定义文件中的问题“更深”。 TypeScript 在处理布尔类型方面似乎发生了一些变化。因此,我没有将这个问题标记为 Knockout.js 问题,而是创建了一个受 Knockout d.ts 启发的小代码示例来说明该问题:

interface Observable<T>
{
  (): T;
  (value: T): any;
}

function observable<T>(value: T): Observable<T>
{
  return undefined as any;  // the implementation is not important
}

const x: Observable<boolean> = observable(false);

此代码有一个编译问题:

Type 'Observable<false>' is not assignable to type 'Observable<boolean>'.
  Types of parameters 'value' and 'value' are incompatible.
    Type 'boolean' is not assignable to type 'false'.

当然将 false 转换为boolean 有效,但我确实认为这是黑客,而不是解决方案(显然我们需要对每次出现的 true/false 进行强制转换)。 有什么办法可以真正解决这个问题吗?

编辑:根据评论,显然某些类型检查已更改。更多示例请参见此处。 <一href="https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgPICMDO0Bud0A2EAPACoB8AUAN6XLIAUAl AFzKkDcdjeBArhDalWyOCACeXAL6VKMPiARhgAexDIVWXPiJlyDXgKEiM2KHkIkKNblAhg+UdQoAmEGKAgvRmURI70APSByGAAFij AALYADKRREOBwymrIwL4gKmBpsSpQYGJglDKUYOIxKAAKCOIJ4ACy9mEq3gC8yADkCHCYYR3IAD6d3VAuHQGyCGqY2QAebKbalsT oKipEYuTI7ZpmFkQM8ATYTFxTIDPI4gta5jok1bWJYI3hLVs7t-sQDF09fadkJRzpcAF43Pb3YggPhRdDQADaAF0PhovvcGMjAUA" rel="nofollow noreferrer">Playground 链接。

此更改有任何信息(带解释)吗?

Edit2:根据评论中的建议,我在 https://github.com/microsoft 提交了错误报告/TypeScript/issues/48150

We are using Knockout.js (v3.5.0) and its TypeScript definitions. They worked OK until TypeScript 4.6.2. However the problem seems to be "deeper" than in the definitions file. It seems that there was some change in TypeScript in handling a boolean type. So rather than tagging this question as Knockout.js problem, I created small example of code inspired by the Knockout d.ts that illustrates the problem:

interface Observable<T>
{
  (): T;
  (value: T): any;
}

function observable<T>(value: T): Observable<T>
{
  return undefined as any;  // the implementation is not important
}

const x: Observable<boolean> = observable(false);

This code has one compilation problem:

Type 'Observable<false>' is not assignable to type 'Observable<boolean>'.
  Types of parameters 'value' and 'value' are incompatible.
    Type 'boolean' is not assignable to type 'false'.

Of course casting the false as boolean works, but I do consider this as hack, not a solution (obviously we need cast on every occurrence of true/false).
Any way to actually solve this?

Edit: based on comment it is obvious that some type checking was changed. More examples can be seen here. Playground Link.

Is there any info (with explanation) for this change?

Edit2: as suggested in comments, I filed a bug report at https://github.com/microsoft/TypeScript/issues/48150

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

假扮的天使 2025-01-18 04:59:20

我建议改为显式指定泛型类型,例如:

const x = observable<boolean>(false);

这样做的原因是我们假设 false 暗示 boolean。通常是这样,但并非总是如此。想象一下这些类型

const x = observable<false | undefined>(false);
const y = observable(false);

(对于任何试图以任何其他方式解决打字问题的人,请确保上面的行也有效。)

I would suggest to instead explicitly specifying the generic type like:

const x = observable<boolean>(false);

The reason for this is that we are assuming that false implies boolean. Usually it does, but not always. Imagine e.g. these types

const x = observable<false | undefined>(false);
const y = observable(false);

(For anybody trying to solve the typing problem in any other way, please make sure that the above lines are also valid.)

雨落星ぅ辰 2025-01-18 04:59:20

根据已回复 Github 问题的用户 (https://github.com/microsoft/TypeScript/issues/48150) Typescript 4.6 编译错误是预期的:

我相信这是一个正确的错误,在旧版本中没有正确处理。
通用参数 T 是不变的,因为它用在协变位置 () => 和 () => 中。 T和逆变位置(值:T)=>任何。

这确实是事实。由于用户帮助解决了问题,为了完整起见,我将尝试在这里重新表述和总结他的评论。

第一个提出的解决方案仅部分解决了问题:

function observable<T>(value: T extends infer U ? U: never): Observable<T>
{
  return undefined as any;  // the implementation is not important
}

const x: Observable<boolean> = observable(false); // no error

但是,这将产生没有类型注释的未知类型。

const bad = observable(false);
//     ^ unknown, which should be Observable<boolean>

正确的解决方案似乎是引入了另一种类型参数

declare function observable<T, U = any>(value?: T extends infer R ? R : U): 
    unknown extends T ? Observable<U> : Observable<T>

Playground 链接

由于主要问题与 Knockout.js 库有关,因此我在那里提交了该问题 (https://github.com/knockout/knockout/issues/2589),希望有足够 Typescript 知识的人能够纠正这个问题。

According to the user who has responded to the Github issue (https://github.com/microsoft/TypeScript/issues/48150) the Typescript 4.6 compilation error is expected:

I believe this is a correct error which was not handled properly in old versions.
The generic parameter T is invariant as it is used in both a covariant position () => T and a contravariant position (value: T) => any.

which is indeed true. Since user helped solve the problem, for sake of completeness I will try to rephrase and summarize his comments here.

The first proposed solution solves the problem only partially:

function observable<T>(value: T extends infer U ? U: never): Observable<T>
{
  return undefined as any;  // the implementation is not important
}

const x: Observable<boolean> = observable(false); // no error

however that will produce unknown type without a type annotation.

const bad = observable(false);
//     ^ unknown, which should be Observable<boolean>

The correct solution seems to introduce another type parameter

declare function observable<T, U = any>(value?: T extends infer R ? R : U): 
    unknown extends T ? Observable<U> : Observable<T>

Playground Link

As the main issue was with the Knockout.js library, I filed the issue there (https://github.com/knockout/knockout/issues/2589), hopefully someone with enough Typescript knowledge will correct the problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文