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 类型、泛型和抽象类 的相关文章

  • Kotlin 中扩展函数的多态性

    我有几个我无法控制的课程 我已经在几个常见的 属性 上创建了几个同名的扩展方法 名称相同的扩展函数始终返回相同的值类型 尽管针对每种类型的接收器以不同的方式计算 这里有一个简化的基于仅一个属性的内置类型的示例 DOES NOT COMPIL
  • 尽管设置了元数据,Reflect.getMetadata() 返回未定义

    我正在尝试在我的 TypeScript 应用程序中使用注释 但是我一定做错了什么 因为Reflect getMetadata 总是返回undefined 尽管我可以在调试器中看到元数据似乎设置正确 my class ts 带有带注释的属性
  • 类内的枚举(TypeScript 定义文件)

    我已经四处搜寻 但似乎找不到答案 希望您能提供帮助 如何添加枚举Image 这是我理想的情况 但我得到了一个错误 declare module Lib export module Graphics export class Image en
  • Exceljs:迭代每行和每列的每个单元格

    我想在所有单元格中添加粗边框 这是一个有角度的项目 我正在使用打字稿 我可以为 1 个单元格做到这一点 worksheet getCell A1 border top style thick left style thick bottom
  • 具有泛型类属性的 LINQ 表达式

    我想将 IQueryable 和 id 数组传递给一个根据这些 id 过滤 IQueryable 的方法 由于 ids 可以是 long 或 int 所以应该通用地解决 我想出了以下几点 public static IEnumerable
  • 创建一个扩展来从 Swift 中的数组中过滤 nils

    我正在尝试编写一个 Array 扩展 它将允许可选 T 数组转换为非可选 T 数组 例如这可以写成一个自由函数 如下所示 func removeAllNils array T gt T return array filter 0 nil r
  • Java 通用问题

    下面的代码可以编译 但如果我取消注释行 它不会编译 我很困惑为什么 HashMap 确实扩展了 AbstractMap 并且声明映射的第一行可以正常编译 import java util AbstractMap import java ut
  • 模块转换为 Typescript 后没有默认导出

    我已将 JavaScript 代码转换为 Typescript 并收到错误 模块没有默认导出 我尝试过使用花括号导入并使用 module exports 导出 但它们都不起作用 contactController ts const cont
  • 为什么 Angular 4.3 中的 httpclient 返回 Object 而不是 any?

    Angular 4 3 中的新 HttpClient 类似乎又回来了Object代替any默认情况下 鉴于打字稿文档所述 这样做是否有特殊原因 永远不要使用数字 字符串 布尔值或对象类型 这些 类型指的是几乎从未使用过的非原始装箱对象 适当
  • viewChild如何获取Angular2中添加了js的元素?

    如果一个 HTML 元素已添加到 DOM 中 例如单击按钮后 我们如何访问该元素 viewChild 看不到它 更新1 更多说明 我用过 jquery 数据表 jquery dataTablesdefineTyped 版本 https gi
  • 如何使用Vue3中的ref访问父组件中的子组件方法?

    我正在尝试使用 vue3 和 ref 方法访问父组件中的子方法 但它返回一个错误 未捕获的类型错误 addNewPaper value savePaper 不是函数 下面是我的代码 请指导我哪里错了 子组件
  • For 循环覆盖 HTML 中的文本

    我的数组称为myEmployees其中有 5 个名字 但当我运行代码时 它只打印出其中的 3 个 我相信这种情况正在发生 因为for脚本中的循环会覆盖它在 HTML 文档中编写的前一行 我怎样才能解决这个问题 年度公告板公告 恭喜泰勒 你在
  • 如何在 WebStorm 中“运行”TypeScript 文件?

    在我的 WebStorm IDE 中 所有 js and jsx 我的项目中的文件有一个关联的 运行 命令 但此功能不存在 ts or tsx files 我相信我已经为 TypeScript 正确配置了我的项目 因为我至少能够运行tsc从
  • 如何修复 no-unsafe-any 规则?

    我在用着TSLint https github com palantir tslint检查我的 Angular TypeScript 代码 我启用了no unsafe any https palantir github io tslint
  • 在 Swift 中使用模板键入别名声明

    如何避免函数中多余的限制声明f0 f1 f10 class SomeClass
  • 如何让热模块重新加载在打字稿 monorepo 中工作

    因此 在过去的几天里 我一直在尝试在基于 Typescript React Koa Mongo 的 monorepo 中进行热模块重新加载 但完全徒劳无功 我感觉我的头一直在撞砖墙 HMR 的文档少之又少 几乎互联网上的所有内容都只是par
  • 如何使用 Angular 5 在单击按钮时调用多个方法?

    我正在使用 Angular 5 并面临问题 我想提交 点击 事件并一一调用两个或多个方法 请给我想法或解决方案 以便我可以提交 点击 事件并调用两个或多个方法 such as html 文件
  • 如何通过反射访问Generic.List的索引?

    好的 我有一个类 我将一个对象作为属性传递 我传递的对象是List
  • 如何按顺序使用 RxJS 可观察量?

    事情是这样的 我有一个 HTTP get 请求 它返回一个 JSON 对象列表 我使用 RxJS 订阅接收该列表的数据 现在 对于该列表中的每个对象 我想执行另一个 HTTP 请求 然后将该请求的结果放入数组中 到目前为止 我已经能够做到这
  • 在 C# 中使用 as 关键字与泛型类型发生冲突的编译时行为

    当尝试对无法转换为的非泛型类型使用 C as 关键字时 编译器会给出无法转换类型的错误 但是 当对泛型类型使用 as 关键字时 编译器不会给出错误 public class Foo public class Bar

随机推荐

  • 在我的 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