Typescript 类型、泛型和抽象类

2023-12-10

我尝试了一种对我来说似乎很奇怪的行为。

让我们考虑以下示例(在 Typescript Playground 中测试它):

abstract class FooAbstract {
    abstract bar() {}
}

class Foo extends FooAbstract { 
    bar() { 
        return { bar: 'bar' };
    }
}

class FooMaker<FOO extends FooAbstract> {  
    constructor(public foo: FOO) {}

    bar() { 
        return this.foo.bar();
    }

    baz = () => { 
        return this.foo.bar();
    }
}

let foo = new Foo();
let result = foo.bar();

let foomaker = new FooMaker(new Foo);
let foo2 = foomaker.foo; // Type "Foo", OK
let result1 = foomaker.foo.bar(); // Type "{bar: string}", OK
let result2 = foomaker.bar(); // Type "{}", ???
let result3 = foomaker.baz(); // I've seen comments about using a lambda... Not better

result2 and result3像摘要一样输入bar功能 ({})。看起来this没有被解析为具体类Foo但作为抽象类FooAbstract。而类型foo2表明该类foo属性已正确解析。

到底是怎么回事?我是否以错误的方式做事?


update

事后看来,这个案例可以重新表述如下(在 Typescript Playground 中测试它):

class Foo {
    bar() {
        return { bar: 'bar' };
    }

    getThis(): this {
        return this
    }
}

class Wrapper {  
    bar<FOO extends { bar(): {} }>(foo:FOO) {
        return foo.bar();
    }
}

let wrapper = new Wrapper();
let result = (new Foo()).bar();
let result2 = wrapper.bar(new Foo());

result有类型{bar:string}
result2有类型{}(来自界面)。
wrapper.bar有类型Wrapper.bar<Foo>(foo: Foo): {}

通过这个示例,可以更清楚地看出,即使知道FOO键入为Foo, 打字稿 uses FOO定义而不是其显式类型bar返回类型。


update 2

好吧,在与打字作斗争的同时,我想我已经升级了。这个概念确实是隐式类型打字稿即使推导了类型,也不遵循任何继承模型。嗯,我还是想知道why or 它会改变吗,但我必须应对“就是这样”。所以在这种情况下,类型必须是显式的。

我找到了一种更简单的方法来编写他的示例(在 Typescript 游乐场尝试一下):

abstract class FooAbstract {
    abstract bar(): {}
}

class Foo extends FooAbstract { 
    bar() { 
        return { bar: 'bar' };
    }
}

class FooMaker<FOO extends FooAbstract, BAR> {  
    constructor(public foo: FOO & { bar: () => BAR } ) {       
    }

    bar():BAR { 
        return this.foo.bar() as BAR;
    }
}

let foomaker = new FooMaker(new Foo());
let result = foomaker.bar();

result获取类型{bar:string}并且无需到处放置泛型。里面的东西FooMaker.constructor通过使用泛型引用接口,参数类型可以变得更清晰。


这就是关于 bar 函数的类型解析如何工作的全部内容:

bar() { 
    return this.foo.bar();
}

What is this.foo? FOO或者更准确地说,一个扩展的类FooAbstract,因为与属性不同foo, bar不暴露FOO。必须在定义实际类型 FOO 之前确定类型。

如果你真的想输入它,你必须这样做:

abstract class FooAbstract<T extends {}> {
    abstract bar(): T
}

class Foo extends FooAbstract<{ bar: string }> { 
    bar() { 
        return { bar: 'bar' };
    }
}

class FooMaker<FOO extends FooAbstract<BAR>, BAR> {  
    constructor(public foo: FOO) {}

    bar():BAR { 
        return this.foo.bar();
    }

    baz = (): BAR => {
        return this.foo.bar();
    }
}

let foo = new Foo();
let result = foo.bar();

let foomaker = new FooMaker<Foo, { bar: string}>(new Foo);
let foo2 = foomaker.foo; // Type "Foo", OK
let result1 = foomaker.foo.bar(); // Type "{bar: string}", OK
let result2 = foomaker.bar(); // Type "{bar: string}", OK
let result3 = foomaker.baz(); // Type "{bar: string}", OK

不幸的是,您必须显式定义 FooMaker 的类型,但您确实会阻止这样的事情:

let foomaker = new FooMaker<Foo, { bar: number}>(new Foo);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Typescript 类型、泛型和抽象类 的相关文章

随机推荐

  • 在我的 Ember.js 应用程序中的 localStorage.clear() 或 deleteRecord() 之后,本地存储数据被复活

    我观察到数据复活后localStorage clear or deleteRecord jsbin 示例 在我的 ember 应用程序中被调用 请按照以下步骤复制问题 打开 chrome web dev gt 资源 gt 本地存储 gt h
  • 根据单元格值脚本将行移动到另一个工作表

    希望使用脚本根据谷歌表格中的值移动单元格 在观看了一些有关基础知识的视频并使用网站上找到的代码之后 尝试使这适用于我的电子表格 这对所有这些都是超级绿色的 function doneCopy var app SpreadsheetApp v
  • Python 请求重定向登录

    这是一个网站http pro wialon com 我想使用 python requests 模块登录 登录和通过是演示 import requests with requests Session as c url http pro wia
  • 如何在 webview 中从我的资源加载图片?

    我想加载 WebView 中可绘制资源中设置的名为 map png 的图片 我在另一个答案中发现了这个建议 webview loadUrl file 但我不明白如何正确设置它 我总是收到错误消息 提示找不到所请求的文件 这是我写的 publ
  • 如何在CreateProcess实例化的命令中使用或扩展环境变量?

    下面的代码利用CreateProcess使用环境变量运行命令 在这里 它尝试运行notepad APPDATA test txt 如果我跑notepad APPDATA test txt直接在Windows CMD APPDATA 将被扩展
  • bash 中的命令替换与函数调用

    我正在从一本书中编写一个 shell 脚本 有一个示例 我正在创建一个函数并稍后调用该函数 function name 但据我所知 我可以通过编写函数名称来调用函数 那么 用函数名调用函数和用函数调用有什么区别 function name
  • 正则表达式获取以冒号分隔的键值对中的文本

    我这里有我的正则表达式示例 https regex101 com r kE9mZ7 1 对于以下字符串 key 1 一些文本 可能是逗号 以分号结尾 key 2 可能没有结束分号的文本 但也可以是 我想做如下的事情 var regEx at
  • VB CStr、CDate、CBool​​ 等与 DirectCast 进行无需转换的投射

    我通常避免使用 VB 的内置转换函数 CStr CDate CBool CInt 等 除非我需要进行实际转换 如果我只是进行转换 例如从对象到字符串 我通常使用 DirectCast 或 TryCast 假设 CStr 等正在执行一些我不需
  • 如何保存onClickListener的状态?

    我有一个实现多个 onClickListener 的程序 因此 随着用户点击按钮的进展 是否有办法保存用户在离开应用程序或被销毁之前使用的 onClick 侦听器 使用共享首选项来实现这一点 每当您单击任何按钮时 都会存储按钮名称及其值 e
  • Android 上的 idHTTP 不可接受错误 406

    我正在尝试使用 idHTTP 和 PHP 脚本在 MySQL 数据库上发布插入 这是要插入数据库的 PHP 脚本 mysqli new mysqli servidor usuario senha banco Caso algo tenha
  • 为什么我无法编译这个命令行 OpenCV Mac 应用程序?

    以下是我的步骤 1 创建命令行工具项目 OpenCV 2 在 usr local lib下的工程中添加后缀为2 4 2的文件 如 libopencv calib3d 2 4 2 dylib 3 将 usr local include 添加到
  • Kiwi 和 CocoaPods 具有静态共享库

    我有一个包含 3 个项目的工作区 MyApp Common Pods Common是MyApp依赖的公共库 我想设置 CocoaPods 和 Kiwi 以便在此项目中正常工作 我该怎么办 I found https stackoverflo
  • Slickgrid:最终列自动调整大小以使用所有剩余空间

    我正在使用 SlickGrid 并努力寻找一个优雅的解决方案来解决以下问题 所有列在首次渲染时必须具有特定的初始宽度 但之后可以调整大小 调整窗口大小时 最后一列应自动填充剩余的列空间 我见过 使一列填充 SlickGrid 中的剩余空间
  • 使用新的架构更改更新 LinqtoSql 数据库?

    我有一个已发布到市场的 Windows Phone 7 应用程序 我将 Sql CE 与 LinqToSql 一起使用 当应用程序运行时 它会通过连接字符串检查数据库是否存在 如果不存在则创建数据库 using CheckbookDataC
  • 在 Google Apps 脚本中转义正则表达式文字

    我不知道为什么这不起作用 我已经通过我在网上找到的更好的正则表达式工具之一来验证它 并且我之前使用的似乎是转义字符 号使其成为字面 但 Google 脚本一直抱怨 无效量词 第 2 行 这是我的脚本 省略了某些个人详细信息 这是为了清理电子
  • Django - 将额外参数传递给 upload_to 可调用函数

    我知道您可以使用 upload to 参数传递可调用函数来动态更改 Django 模型中的 FileFied ImageField 等 upload to 调用的函数传递了 2 个变量 即未保存在数据库中的文件的实例 instance 和所
  • 将分组平均值添加到数据框中的列[重复]

    这个问题在这里已经有答案了 我想计算数据框中的组平均值 并在包含这些组平均值的原始数据框中创建一个新列 我正在进行重复性研究 我想要新列中插入 单元和通道内测量的平均值 以便我可以将其减去并计算残差 My data gt head myte
  • 如何在 HttpPost 中使用参数

    我正在通过以下方法使用 RESTful Web 服务 POST Consumes application json Path create public void create String str1 String str2 System
  • 定期运行 JavaScript 函数

    我目前正在建立一个网站来托管软件 我想要的是在项目页面中添加循环截图的幻灯片 大约每 5 秒更改一次图像 有没有办法仅使用 JavaScript 在一定时间间隔触发脚本 或者我是否必须采用替代方法来实现我想要的功能 预先感谢您的任何帮助 s
  • Typescript 类型、泛型和抽象类

    我尝试了一种对我来说似乎很奇怪的行为 让我们考虑以下示例 在 Typescript Playground 中测试它 abstract class FooAbstract abstract bar class Foo extends FooA