Typescript: 自定义转换器的插件支持

创建于 2017-03-02  ·  99评论  ·  资料来源: microsoft/TypeScript

由于#13764 已经登陆,编写自定义转换器很容易。 但是,如果我正确理解 API,则需要复制整个 tsc 命令行以添加单个转换器。 这会导致不兼容,因为这些取决于打字稿的应用程序不支持与 tsc 命令行工具相同的功能。

因此,最好有一个插件系统,允许从第三方节点模块加载自定义转换器,因为语言服务代理 #12231 就是这种情况。 然后,这些转换器很容易集成到现有的构建工具/构建工作流程中。

如果有经验的人对如何实施更改有意见,我愿意创建一个 PR,因为它会极大地简化我的项目。

最有用的评论

我不想有一个暴露的插件 API。 相反,我更喜欢通过在 tsconfig.json 中指定它们来注册我的自定义转换的方法,而不必使用 TS-Compiler API。 因为使用 TS-Compiler API 意味着我不能再使用 tsc 命令行工具,这进一步意味着它不再很好地集成到现有的构建工具和工作流中。

所有99条评论

我们不打算在短期内公开编译器插件系统。 如您所述,转换作为公共 API 的一部分公开,我们正在为这些编写文档和示例。

我不想有一个暴露的插件 API。 相反,我更喜欢通过在 tsconfig.json 中指定它们来注册我的自定义转换的方法,而不必使用 TS-Compiler API。 因为使用 TS-Compiler API 意味着我不能再使用 tsc 命令行工具,这进一步意味着它不再很好地集成到现有的构建工具和工作流中。

有关文档和示例的任何更新? @mhegazy

@MichaReiser ,您可以编写一个基于 API 的简单编译器(此处为示例)。 实际上,我们在 Yahoo Finance 中大量使用 TS,并且 Transformer 公共 API 非常棒。

这些是我们在公开后编写的一些变形金刚:
https://github.com/longlho/ts-transform-system-import
https://github.com/longlho/ts-transform-img
https://github.com/longlho/ts-transform-react-intl
https://github.com/longlho/ts-transform-css-modules-transform

@mhegazy lmk如果您需要帮助记录/收集样本

@longlho
感谢您的样品。

这就是我目前正在做的事情。 但是,无法使用为 typescript 创建的其他构建工具,例如 web pack 加载器、jest 加载器。 此外,当我们每个人都使用不同的前端时,我如何才能将您的一个插件与我的一个插件一起使用?

因此,我确实相信当前的方法是一个好的开始,但对于插件生态系统来说还不够。 因为使用插件对用户来说太费力了,需要的不仅仅是为作者编写转换代码。

如果目标是鼓励社区创建和使用自定义转换器,我相信像 Babel 这样的插件系统对于打字稿来说是必不可少的。

@MichaReiser 是的。 我并不是说它对于生态系统来说已经足够了,只是对于迈向它的第一步来说已经足够了。

我想在 gulp-typescript 中添加对转换的支持,但我想防止所有 TypeScript 插件(用于 gulp、webpack 等)提出不同的 API。 并且 TypeScript 可能会在以后添加一种不同的方式来配置它。 那么您目前是否有计划在近期或远期添加此功能?

大家好,我尝试编写一个预处理器,但没有任何结果:[

其实我有两个问题:

  • 如何从字符串创建 AST 片段?
  • 如何添加导入?
// 1. Input
class Foo {
    templateString = 'some value';
}

// 2. After transformation
import __LIB__ from '@external/lib';

class Foo {
    templateString = (function compiledTemplate(deps) {
        // ...
        return result;
    })({lib: __LIB__});
}

// 3. Expected result
var lib_1 = require("@external/lib");
var Foo = (function () {
    function Foo() {
        this.templateString = (function compiledTemplate(deps) {
            // ...
            return result;
        })({ lib: lib_1 }); 
    }
    return Foo;
}());

一个简化的例子: https ://github.com/RubaXa/typescript-api-questions/tree/master/import-add

⬆️⬆️⬆️
@longlho@mhegazy你能给点提示吗?

@RubaXa由于您在转换中添加了导入声明,因此它没有被绑定或类型检查。 由于它没有被绑定或类型检查,我们无法将表达式中的 $ __LIB__解析为声明中的__LIB__

一种选择是使用命名空间导入而不是默认导入,这样您的发出类似于:

import * as __LIB__ from "@external/lib"

因为不会发生混叠。

另一个保留为导入声明生成的标识符,根据附加的 zip

@RubaXa如果您的目标是传入整个模块对象,您可能希望使用import * as __LIB__ from "@external/lib"语法(不需要别名)而不是import __LIB__ from "@external/lib"因为后者导入default导出而不是整个模块对象。

是的,我们也在CSS 模块转换器中使用import * as foo来防止混叠。 虽然利用它来内联某些命名导出会很好

@rbuckton O,非常感谢!
仍然对如何从字符串创建任意 AST 片段感兴趣?

function createFragmentFromString(code: string) {
  // ????
}

function visitPropertyDeclaration(node) {
    if (ts.isIdentifier(node.name) && node.name.text === "templateString") {
        // ...
        return ts.updateProperty(
            node,
            ts.visitNodes(node.decorators, visitor),
            ts.visitNodes(node.modifiers, visitor),
            ts.visitNode(node.name, visitor),
            ts.visitNode(node.type, visitor),
            createFragmentFromString('(function compiledTemplate() { /* ... */ })()')
        );
    }
    return node;
}

这就是我希望转换器支持和工作流程在 TypeScript 中的表现。

https://www.dartlang.org/tools/pub/transformers

我也对这个功能非常感兴趣。

正如@MichaReiser提到的
If someone experienced has inputs on how to implement the changes, I'm willing to create a PR as it would simplify my project tremendously.

喜欢看到专家/打字稿编译器 DEV 的输入。

看起来有人包装了打字稿以公开此功能。 https://github.com/cevek/ttypescript

看起来 ts-loader 也有它: https ://www.npmjs.com/package/ts-loader#getcustomtransformers -----before-transformerfactory--after-transformerfactory----

我认为这可能会出现在 typescript 2.8 版本中,或者至少在某个时候出现在路线图中, @ahejlsberg @mhegazy @DanielRosenwasser你怎么看? 通过这种方式,定制变压器可能更受欢迎,因此更强大。 从 tsconfig.json 的角度选择在 transfromer 中插入插件将大大简化生活。

如前所述,我们没有计划在短期内公开插件。

@mhegazy这是一个经过深思熟虑的决定,还是仅仅因为社区兴趣低而超出范围?

我没那么说过。 我们希望保持较小的公共 API/可维护性成本以及更改构建向前推进方式的灵活性,而这两者都受到插件模型的影响。

请停止变压器插件 api 碎片。 在变压器 api 之上稳定插件 api 并在 tsconfig.json 中公开它们。

ts-loaderparcel-plugin-typescriptrollup-plugin- typescript2 、 ts-transformer-keysttypescript等。

它们每个都提供自定义插件注册方法和自定义插件入口点格式。 这是 ts 插件地狱的一种方式。

现在cevec/ttypescript支持所有常见的转换器插件格式。 它是所有 typescript 模块和 tsc、tsserver 命令(只是小型运行时 ts.createProgram 补丁)之上的一个插入式包装器。 Webpack ts-loader 和 rollup-plugin-typescript2 可以使用 ttypescript 轻松配置。

TTypescript 建议通用转换器插件格式,但也支持现有转换器。

{
    "compilerOptions": {
        "plugins": [
            { "transform": "ts-transform-graphql-tag" },
            { "transform": "ts-transform-css-modules", "type": "config" },
            { "transform": "ts-nameof", "type": "raw", "after": true}
            { "transform": "./transformers/my-transformer.ts", "someOption1": 123, "someOption2": 321  }
        ]
    },
    "exclude": ["node_modules", "transformers/**/*"]
}

这个有消息吗? 在我看来,TypeScript 作者似乎不希望在 vanilla TypeScript 上允许自定义转换器 - 真可惜,这将是一个很棒的功能。

他们不希望维护另一个 api/surface,因为担心会导致难以破坏内部的东西。 具有讽刺意味的是,所有这些 3rd-party 插件解决方案,因为 ts-team 没有标准,都有些不同,最终都会崩溃。

他们不希望维护另一个 api/surface,因为担心会导致难以破坏内部的东西。

在使用 typescript 工作了 3 年并观察了它的演变之后,我得出了一个简单的结论。 Microsoft 在_code_ 的意义上已经开源了 Typescript,但在_process_ 的意义上没有。 在大多数情况下,开源项目在决策编码方面或多或少都是由社区驱动的,这应该是发展的自然方式。 你还记得 node.js 的 IO.js fork 吗? 社区意识到公司利益与常见的开源治理模型并不一致,他们只是分叉了。 我希望 TypeScript 不会发生这种情况,但微软应该考虑到这种可能性。
需要明确的是,我并不是在责怪开发人员,无论如何,他们确实做得很好。
只是我的2c,对不起OT。

微软在代码的意义上已经开源了 Typescript,但在流程的意义上没有。

我完全不同意这一点。 我从未在 Microsoft 工作过,但在过去的 4 年中,我对 TypeScript 的几个特性产生了直接影响。 我代表的是一个用 TypeScript 构建的开源库,我们安排了一些直接的对话,但是关于任何功能的所有“辩论”都是在这里公开进行的。 核心团队发布他们的设计会议记录。 我得到的唯一一个代表开源库的“内部人员”是一个机会,可以亲自为我的某些功能辩护,并与核心团队会面。 这让我意识到团队是一个团队。 我们谈到的一个功能,安德斯基本上说这个问题太难了,需要很多时间来解决它并解决人们面临的“真正”问题。 那是两年前的事了,在 TypeScript 3.0 中我们终于明白了。 但是社区在设计过程中有发言权,但就像任何社区一样,我们有各种不同的声音,任何地方的团队都不能取悦所有人,如果他们这样做了,TypeScript 将是一个_非常_糟糕的工具。

你还想给核心团队贴上“微软”的标签。 核心团队是我遇到过的最少的微软团队。 在完全控制发布内容之后,他们为完全控制发布节奏而进行了战斗。 他们还为公开和透明而奋斗。 为从 CodePlex 迁移到 GitHub 而奋斗。 诚然,它们在 Microsoft 中不再那么独特了,因为其他几个团队已经采用了他们的模型,但据我所知,他们是这一切的发起者,VSCode 团队紧随其后。

因此,仅仅因为核心团队选择并选择他们的战斗,坚持他们的设计原则并不意味着社区没有声音,但作为一个声音,我们患有精神病性多重人格障碍。 我们是一个难以服务的客户。

我的理解是这与#16607 相同,或者这会达到不同的目标吗? 作为我自己最近的插件作者,我也希望看到这一点 - 包括使用 Babel 插件使用 TypeScript 时。

@mrmckeb这个问题是为了标准化和公开已经存在的打字稿 AST 转换,而链接的问题似乎是在非常广泛(未定义)的范围内讨论整个文件转换。

我想在这里加我的 2 美分。 你们中的一些人可能听说过babel-plugin-macros的精彩项目。 基本上,与其拥有数千个不同的 Babel 插件,不如只有一个由用户代码驱动以进行转换。 一个非常透明的系统,无需一直搞乱配置。 这对于像CRA这样支持宏但禁止额外配置的项目尤其有用。

今天我已经开始讨论如何将它带到 TypeScript 世界。 如果您有一些见解,请务必过来分享。

最终,我希望如果我们以某种方式成功,就不需要这样做,因为只需要一次转换。

@FredyC这是一个很酷的项目,但我们需要解决这个问题,以便在仅使用tsc时轻松地将类似的东西注入编译器。 例如,对于 babel-plugin-macros,它仍然需要在.babelrc中指定,并且最好在 tsconfig.json 的typescript中指定类似的内容。

实际上,您是否建议在 TypeScript 中内置类似 babel-plugin-macro 的行为并且不需要配置? 这可能很好,但我个人更喜欢一个可配置的解决方案,它允许在tsconfig.json中指定自定义转换器,然后可以指定支持 typescript ast 节点的 babel-plugin-macros 版本。

@dsherret是的,我不希望它成为 TypeScript 本身的一部分。 但是,我可以想象,一旦转换准备就绪,就可以很容易地准备一个类似tsc的微型包装器,该包装器将只为宏注入该转换,其余部分可以从用户代码中完成。

编辑:实际上,微型包装器已经存在,上面提到的https://github.com/cevek/ttypescript很容易指示将它与通用宏插件一起使用,这是双赢的。

我只需要找到精通 Typescript 转换的人来确定一些基本原型。 我可以讨论和交谈,但实施它超出了我目前的技能。

他们不希望维护另一个 api/surface,因为担心会导致难以破坏内部的东西。

在使用 typescript 工作了 3 年并观察了它的演变之后,我得出了一个简单的结论。 Microsoft 在_code_ 的意义上已经开源了 Typescript,但在_process_ 的意义上没有。 在大多数情况下,开源项目在_decisions_和_coding_中或多或少都是由社区驱动的,这应该是进化的自然方式。 你还记得 node.js 的 IO.js fork 吗? 社区意识到公司利益与常见的开源治理模型并不一致,他们只是分叉了。 我希望 TypeScript 不会发生这种情况,但微软应该考虑到这种可能性。
需要明确的是,我并不是在责怪开发人员,无论如何,他们确实做得很好。
只是我的2c,对不起OT。

我同意。 很明显,尽管社区对此非常感兴趣,但开发人员只是简单地拒绝了自定义转换器/宏的想法,而实际上并没有提供拒绝的理由,除了“人们会滥用它”之类的东西,这听起来也冒犯了社区因为它暗示它是一个低质量的开发者社区。

如果可以提供“我们不会简单地这样做”以外的合理理由,我会接受拒绝,但似乎尽管社区提出了所有要求,但似乎没有人努力提供这一点。

我认为这是不公平的批评@pietrovismara。 我同意这是一项必备功能,但这并不是“微软”阻止此功能。 据我了解,该团队表示这并不容易支持,这就是他们尚未添加此类功能的原因。

再说一次,我和其他人一样想要这个功能——但我们需要用事实来讨论这个问题。 事实是团队还没有准备好支持它。 因此,让我们继续表达兴趣,但也要让对话保持在正确的轨道上。

@mrmckeb如果是这样,我可以理解。 那时,我一定在这些问题中包含的大量评论中错过了这样的声明。 没有冒犯任何人的意思,只是想引起管理员的明确回答,以便如您所说,使对话保持在正确的轨道上。

没关系,令人沮丧的是,不存在对此的支持——正如我所说,我感觉到了,现在 CRA 一直要求我们为 CSS 模块提供某种解决方案,因为我们有 TypeScript 支持。 我希望它很快就会到来,但我也明白这会给团队带来巨大的风险。

...还在等待:(

是的,还在等待......,但等待什么,有什么事情完成了吗?

现在有比ttypescript更好的解决方案吗?
TypeScript 开发人员最终是否计划支持插件?

您可以创建自己的编译器;-)

有关于这个话题的消息吗? 在我看来,社区已经充分利用了这个特性,可以坐下来收集反馈,最后在配置文件中添加对转换器的支持。 甚至有很多实现可以用作参考。

已经超过 2 年了(哇!)*。 人们是否愿意重新考虑为转换器开放插件的利弊?

我觉得一直以来存在的最初担忧,例如缺乏有关 API 的文档,以及必须支持用户代码 <-> 转换器 <-> API 的网格化,不再那么重要了。 开放插件支持为 babel 之类的包创造了奇迹:通过协作取得进展。 我个人可以特别证明 Babel,我已经广泛使用了它。

像 typescript 这样的转换器更容易“正常工作”集成-会很好。 特别是这个包,我认为它对整个打字稿产生了革命性的影响。 真正的强合同! 😃

我认为关于利弊的对话将有助于消除对此的任何沮丧或分歧。 我有一种感觉,这个僵尸问题会一直持续到这种情况发生——老实说。

* 与此同时,有人为 TS 创建了该功能( ttypescript )。 我已经成功地使用了它。

@DanielRosenwasser我看到3.5 迭代计划中有“调查 TypeScript 插件 API”(并且这项工作已经开始)。
这一点是否涉及本期讨论的内容? 缺少一个问题的链接让我认为它太多的 WIP 来分享任何关于它的东西了吗?

我认为应该将工作放在添加对 Babel 解析器的完全支持上,其中包括为 Babel 添加必要的功能以支持 Typescript 静态分析(例如,多个文件转换或转换期间对多个文件的依赖)。 而不必复制语法/将 Babel 插件转换为 Typescript 等价物。

如果您对以下说明有任何疑问,请告诉我,我很乐意为您提供帮助

鉴于设计团队的疏忽,这里有一个解决方法

我们将利用 tslint 及其代码修复功能

在下面的示例中,我们将以最基本的形式进行类型到代码的转换

我们将使用装饰器作为代码中需要重写的地方的标记

在我们的例子中,装饰器是一个伪函数,其唯一目标是

  • 标记转变的地方
  • 并捕获将成为生成器信息源的类型

出于演示目的,我们将把接口的名称和属性类型作为纯字符串转储到底层类中

以下步骤仅适用于 Windows 用户,如果您不是其中之一,愿上帝帮助您:

  1. 启动你的 VSCode
  2. 安装以下扩展: https://github.com/Microsoft/vscode-typescript-tslint-plugin
  3. 关闭你的 VSCode
  4. 转到您选择的文件夹
  5. 运行git clone https://github.com/zpdDG4gta8XKpMCd/code-gen.git
  6. 转到文件夹code-gencd ./code-gen
  7. 跑步

    • 1-install.bat

    • 2-build.bat

    • 3-install-some-more.bat

    • 4-try.bat

  8. 观察打开的 VSCode 实例
  9. 转到test.ts ( Ctrl + P -> test.ts )
  10. 记下下面的接口,它将成为代码生成器的源代码
interface Data {
    one: string;
    another: number;
}
  1. 记下以下函数,它包含一个我们将用作标记的幻像装饰器
function gen<_T>() {
    return function (meh: any) {};
}
  1. 记下重写站点,我们希望在其中推送一些基于界面和标记装饰器的自动生成代码
@gen<Data>()
export class Gen {
}
  1. 观察@gen<Data>()下的波浪线
    image

  2. 选择Quick fix... -> Needs a rewrite, wanna fix?
    image

  3. 观察自动生成的代码:
    image


这里的参考是生成器的源代码,您可以在codeGenRule.ts中找到

import * as Lint from 'tslint';
import * as ts from 'typescript';

export class Rule extends Lint.Rules.TypedRule {
    public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
        return this.applyWithWalker(new Walker(sourceFile, this.getOptions(), program.getTypeChecker()));
    }
}

class Walker extends Lint.RuleWalker {
    constructor(sourceFile: ts.SourceFile, options: Lint.IOptions, private checker: ts.TypeChecker) {
        super(sourceFile, options);
    }
    public visitNode(node: ts.Node) {
        if (ts.isDecorator(node)) {
            const checked = check(node, this.checker);
            if (checked !== undefined) {
                const [node, message, replacement] = checked;
                this.addFailureAtNode(node, message, replacement);
            }
        }
        super.visitNode(node);
    }
}

function check(node: ts.Decorator, checker: ts.TypeChecker) {
    const { expression, parent } = node;
    if (!ts.isClassDeclaration(parent)) return;
    if (!ts.isCallExpression(expression)) return;
    const { expression: identifier, typeArguments: typeArgs } = expression;
    if (!ts.isIdentifier(identifier)) return;
    const { text: name } = identifier;
    if (name !== 'gen') return;
    if (typeArgs === undefined) return;
    if (typeArgs.length > 1) return;
    if (typeArgs.length < 1) return;
    const [only] = typeArgs;
    const type = checker.getTypeFromTypeNode(only);

    // if you got to here, you are at the right place and you have a type

    // working on a fix
    const properties = checker.getPropertiesOfType(type);
    const allNameTypes = properties.map(p => {
        const { name } = p
        const type = checker.getTypeOfSymbolAtLocation(p, node);
        return name + ': \'' + checker.typeToString(type) + '\';'
    })
    const { newLine } = ts.sys;
    const body = newLine + allNameTypes.join(newLine);
    const { pos: start, end } = parent.members;
    return [
        node,
        'Needs a rewrite, wanna fix?',
        Lint.Replacement.replaceFromTo(start, end, body)
    ] as const;
}

@zpdDG4gta8XKpMCd ,感谢您分享您的概念 - 但请保持文明。

鉴于设计团队的疏忽,这里有一个解决方法

这不是解决 TypeScript 未实现您(和许多其他人,包括我自己)想要拥有的 _feature_ 的适当方法。 这不是主要缺陷,也不反映“疏忽”。 请尊重。

哦,请不要把它当作私人的,这只是我开始抱怨的方式,我有一个非常酸的个性(医疗状况),这是我能挤出的最好的,我很抱歉

你们不会停止让我感到惊讶

  • 你看到的是一段似乎能够轻松解决当今主要问题的代码(没有技巧,没有黑客)
  • 这种解决方法是对设计团队的警钟,正如我们之前看到的那样,当社区即将转向错误的方向时,设计团队立即解决了这个问题:#4212,
  • 因此,如果他们关心,他们可以尽快做对,直到为时已晚,或者如果他们不这样做,我们可以自由地朝这个方向挖掘,这对他们来说不会是一个问题
  • 所以我的反馈语气有些不恰当,但自 2017 年 3 月 2 日(超过 2 年)以来,你所有恰当的语气都没有给你带来任何好处,是的,你可以再等 2 年

@zpdDG4gta8XKpMCd您为实际实施做出了什么贡献? TypeScript 是开源的; 我毫不怀疑,如果您创建了一个(甚至是部分),他们会认真考虑一个拉取请求。

将您的粗鲁归咎于医疗状况是不可接受的; 它们是您键入并自愿选择单击“评论”的单词。 没有任何医疗条件可以让你这样做。 说话,也许,而不是打字。 您也有机会编辑您的评论以将其删除,但您还没有这样做。

如果您需要自定义转换器_now_,您可以使用 Babel。 它可以从几乎所有 TypeScript 中删除类型注释,同时允许您随心所欲地进行语法转换。 作为奖励,它也更快。

我建议您在被永久踢出 Microsoft 存储库之前停止评论。 我知道如果这是我的回购,你会是最后一根稻草。

好吧,你把我踢出去了,然后呢
我能回来吗? 我可以创建一个新帐户吗?
你觉得我太在乎这个帐户了吗?

无论如何,是的,我尝试了拉取请求,不幸的是,由于以下原因,这是不可行的:

  1. 欢迎您解决某些类别的问题,这些问题相当琐碎且兴趣不大,像这样严重的事情-您不是

  2. 因为你不能自己解决它,这样的问题(即使有 224 个竖起大拇指)如果考虑的话可能会等待数年

  3. 幸运的是,您今天可以使用您拥有的任何方式做某事并开始做出可见的改变,因此建议(不要怪我什么都不做)

@zpdDG4gta8XKpMCd正如你所知,多年来我一直是愤世嫉俗的粉丝,我必须同意这里的其他人 - 我们需要保持对话的礼貌和尊重。 这总是很好的提醒,每个跟踪此问题的人都希望使项目变得更好


@Janpot是的,这在很大程度上是一个 WIP,尽管当@rbuckton回来时,他可能能够提供更多关于状态的详细信息。

当我们调查插件点时(就像我在 3.5 迭代计划中提到的那样),我认为为自定义转换器公开更简单的钩子是我们要考虑的主要方案。 我们不一定直接这样做的原因是我们可能有更广泛的工作来包含这一点。 换句话说,也许有比前变压器和后变压器更广泛的东西。

@DanielRosenwasser里面没有那么多愤世嫉俗的东西,我只说了两个字,然后我说我对此深感抱歉

无论如何,重点是我认为我们都同意,对于事情的进展,有很大一部分是健康的挫败感,我们不怪你,我们理解是什么推动了这个项目

但如果我们从我们的角度来看,肯定有人要受到责备,因为让这样的问题搁置多年只是收集竖起大拇指,是阻止提高生产力的原因

我相信有理由推迟它并首先关注其他事情,所以我认为如果你让你的观众知道为什么某些非常想要的功能无法实现会更好,它可以降低挫败感,比如:

  • 我们无法实现此功能,因为 A、BC 以及需要先完成 D、E 和 F 的

所以我想我指的是这个对话: https ://github.com/Microsoft/TypeScript/issues/30696#issuecomment -478799258

竖起大拇指不会凭空创造新资源,不会让复杂和困难的决策变得简单容易,不会改变现有的业务优先级,不会停止进行中的项目,不会优先考虑其他工作,不会导致过于雄心勃勃的提案变得范围广泛,或改变具有广泛和永久影响的建议,使其变得专注和可维护。

对于我们在此类极其复杂和高维护的工作之前所做的(或允许为. 不难猜想为什么我们愿意让别人进来修理漏水的水龙头,而改造地下室和在房子顶部增加另一个故事的计划仍在制定中。

@zpdDG4gta8XKpMCd你为什么要责怪别人? 你为什么不首先责备自己没有通过 PR 来解决这个问题呢? 或者至少是一些关于如何从实施的角度处理它的建设性文章?

哦,伙计,即使在你刚刚链接的那篇透明的文章之后,你还是决定在两周后再次戳熊? 试着想象在那个位置上手头有 1500 多个任务,而你必须选择其中的几个。 在我们的团队中,我们正在移动大约 100 个任务并且相当挣扎。 无法想象它会增加 15 倍😮

@FredyC看在上帝的份上,在说我什么都没做之前先看看我的解决方法

是的,我没有做正式的拉取请求,因为:

  1. 我没有达到制作好的水平

  2. 对于简单的,有很长的审批流程,并且需要大量工作才能使 2 年前创建的拉取请求与当前代码库保持同步,我没有那么多时间

  3. 考虑到只有像安德斯·海尔斯伯格这样的少数人知道的宏大设计考虑,某些问题甚至不会被考虑

你不能带走沮丧的部分,我并不孤单

我们知道有以下因素在起作用:

  • 语言的宏伟设计
  • MS内部的预算/资源/政治
  • 社区的愿望

如果混合这些成分的决策更清晰一点,我会更高兴

完了,走得太远了,对所有感情受到伤害的人表示抱歉,我不会说一句话

https://github.com/Microsoft/TypeScript/issues/14419#issuecomment -483920640 的延续

另一种选择是使用函数声明本身作为标记,下面是代码生成器的实现,用于名称以toRandom...开头的函数

生成器的信息源是函数的结果类型

这是它的工作原理:

  1. 注意以toRandom...开头的函数下的波浪线
    image
  2. 探索您的选择:
    image
  3. 快速修复
    image
  4. 观察结果:
    image

这是codeGenRule.ts的代码

作为奖励,如果函数的当前代码与应该生成的代码不匹配,此实现只会引发 linting 问题

import * as Lint from 'tslint';
import * as ts from 'typescript';

export class Rule extends Lint.Rules.TypedRule {
    public applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): Lint.RuleFailure[] {
        return this.applyWithWalker(new Walker(sourceFile, this.getOptions(), program.getTypeChecker()));
    }
}

class Walker extends Lint.RuleWalker {
    constructor(sourceFile: ts.SourceFile, options: Lint.IOptions, private checker: ts.TypeChecker) {
        super(sourceFile, options);
    }
    public visitFunctionDeclaration(node: ts.FunctionDeclaration) {
        const checked = check(node, this.checker);
        if (checked !== undefined) {
            const [node, message, fix] = checked;
            this.addFailureAtNode(node, message, fix);
        }
        super.visitFunctionDeclaration(node);
    }
}

function check(node: ts.FunctionDeclaration, checker: ts.TypeChecker) {
    const { name: identifier, type: result, body } = node;
    if (body === undefined) return;
    if (identifier === undefined) return;
    const { text: name } = identifier;
    if (!name.startsWith('toRandom')) return;
    if (result === undefined) return;
    const type = checker.getTypeFromTypeNode(result);

    // if you got to here, you are at the right place and you have a type

    // working on a fix
    const properties = checker.getPropertiesOfType(type);
    const newerBody =
        `{
    return {${properties.map(prop => {
            const { name } = prop;
            const type = checker.getTypeOfSymbolAtLocation(prop, node);
            const typeName = capitalize(checker.typeToString(type));
            return `
        ${name}: toRandom${typeName}(),`;
        }).join('')}
    };
}`;
    const olderBody = body.getFullText();
    if (areEqual(olderBody, newerBody)) return;
    const start = body.getFullStart();
    const end = start + body.getFullWidth();
    return [
        node,
        'Needs a rewrite, wanna fix?',
        Lint.Replacement.replaceFromTo(start, end, newerBody),
    ] as const;
}

function areEqual(one: string, another: string) {
    // AB: we cannot make any assumption what line endings are,
    // this is why we compare the text of code without them
    return one.replace(/\r\n|\n/g, ' ') === another.replace(/\r\n|\n/g, ' ');
}

export function capitalize(value: string): string {
    const length = value.length;
    if (length > 1) {
        return value.substr(0, 1).toUpperCase() + value.substr(1);
    } else if (length > 0) {
        return value.substr(0, 1).toUpperCase();
    } else {
        return value;
    }
}

@zpdDG4gta8XKpMCd我相信这个问题更多的是关于在发射时插入自定义变压器的更简单方法? 前任。 在 tsconfig.json 中指定转换,以便它们可以与tsc一起使用,而不是使用api 。 您想在编辑器中进行自定义代码更改/修复吗?

我根本没有使用过它们,但我认为您所说的内容可能已经可以通过语言服务插件实现(我认为通过在语言服务上覆盖getCodeFixesAtPosition并插入您自己的代码操作......不过不确定) https://github.com/Microsoft/TypeScript/wiki/Writing-a-Language-Service-Plugin

还是我理解错了?

正确的。 这正是我以前的想法

我认为通过tsconfig.json指定我的自定义转换的方法将是梦想成真

但后来我意识到我更喜欢我的解决方法

这是我的思路:

  • 我需要一个可插拔的可配置代码生成器
  • 打字稿没有那么方便的东西
  • 另一方面,我知道 tslint(虽然在 2019 年底前被贬值)是一个不错的 typescript 插件平台,它可以非常自由地插入和配置你的代码
  • 原来它有我需要的一切:

    • 可插拔和可配置

    • 带有所有必要的用户界面

    • 给了我一个打字稿的 API

    • 有一些额外的东西

鉴于我无法看到自己编写使用打字稿语言服务的东西,因为:

  • 我的笔记本电脑只能容纳那么多打字稿语言服务,其中一些已经是:

    • vscode之一

    • tslint 之一

我不想在此之上添加另一个

我希望我有更好的方法来插入我的代码转换器,但我们拥有我们所拥有的


这就是我们做宏的方式:#4892

  • 我的笔记本电脑只能容纳那么多打字稿语言服务,其中一些已经是:

    • vscode 的一个
    • 一个来自 tslint

@zpdDG4gta8XKpMCd我相信一切都应该使用相同的语言服务。 因此,您将拥有单一语言服务,然后 tslint 插件和您的插件将代理该服务。

顺便说一句,您在这里尝试做的事情绝对应该使用简单的语言服务插件来实现,因为这就是在这里所做的。

无论如何,让我们试着在这里讨论主题,并且只讨论自定义转换器作为构建的一部分,使用tsc而不是编辑器代码更改/语言服务的东西。 大多数人都在寻找一种解决方案来对整个项目进行转换,而在编辑器中进行转换并不是一个可行的解决方案(尤其是因为此时进行转换违背了使用它们的目的)。 理想情况下,这里应该实现的内容应该与编辑器/tsserver 或语言服务无关。

感谢您的宝贵意见,我会考虑

我不同意您将自定义转换器作为构建的一部分与tsc进行对话,因为

  • 书面的原始请求没有具体说明要交付哪种形式的转换,它只是说明他们不应该要求必须
    > 复制整个 tsc 命令行只是为了添加一个转换器
  • 2 年多来,这个讨论引起了很多人的关注
  • 此外,tslint 团队在构建插件基础设施方面做得很好,不使用它是浪费精力,前提是它实际上是 typescript 之外唯一官方认可的处理 typescript 的平台
  • 此外,我们都同意,即使变形金刚能找到使用语言的方法,它也不会很快发生,但这里的人们(包括我自己)像昨天一样需要他们
  • 最后,既然没有那么多更好的选择,我们为什么不至少考虑一下我们有什么?

我的建议被明确标记为一种解决方法(而设计团队正在花时间更努力地思考一个合适的解决方案),那为什么不呢?

如果你坚持我们应该在其他地方做,请说出来

但为了解决您非常担心的问题

在整个项目中进行转换

tslint 的--fix cli 参数正是这样做的

@zpdDG4gta8XKpMCd --fix将更新 TypeScript 代码。 这个问题是关于在发出期间进行转换(因此更改只会出现在最终的 JavaScript 文件中)。 请参阅参考问题的 PR (#13940):

由于#13764 已经登陆,编写自定义转换器很容易。 但是,如果我正确理解 API,则需要复制整个 tsc 命令行以添加单个转换器。 这会导致不兼容,因为这些取决于打字稿的应用程序不支持与 tsc 命令行工具相同的功能。

换句话说,该问题带来了CustomTransformers (单击该链接并查看它在 API 中的使用位置),但为了使用它们, tsc需要以某种方式复制或包装,这就是ttypescript可以。 然后第二段讨论了这将是多么好,因为它可以很好地集成到现有的构建工具中(因为使用自定义转换器将由 tsc 处理,而不是由不同的构建工具以不同的方式来处理)。

我认为打开一个新问题来解决您对代码修复的担忧或想要一种更简单的方法在 TypeScript 代码中生成 TypeScript 代码会更有效率。 我不确定这些问题到底是什么,因为我认为今天已经有很多问题了,但是你一直在讨论的是如何进行代码修复/操作,这对我来说似乎是一个无关的主题。

我认为在这个线程中要回答的主要问题是 Daniel 所讨论的内容——“也许有比前变换器和后变换器更广泛的东西”——以及制作这部分构建的解决方案是什么样的。

你含糊不清

我是一个理解和欣赏简单事物的人

我的问题是我正在处理一个大约 3500 多个文件的项目,其中 15% 不需要手动编写和维护,而且还有大约 5% 的类似内容即将到来

同时我知道有一个 API 可以为我做这件事,但它是如此的半生不熟,我永远无法证明我花时间处理它来让它完全成熟

所以当我来到这里时,我认为这是谈论它的正确地方,结果可能有一个快速简单的解决方案

运气不好有些人来这里是为了讨论一些更美好的事情

好的,优秀!

不,我不会为了再次向人们展示 tslint 如何解决其中一个主要问题而开一个新问题,我完成了我的工作,我完成了

开箱即用的可配置转换会很好。 我正在尝试解决代码内字符串l10ni18n的问题。 我可以利用带有自定义提取规则的tslint之类的工具,但是我转换代码的选项是有限的,除非我使用类似ttypescript的东西,但这是有问题的,因为我的应用程序工作是一个未弹出的角度应用程序。 它只是迫使我添加一层又一层的构建工具。 随着发展的步伐,整个堆栈变得非常不稳定。

我们目前正在开发一个框架,我们目前正在使用ttypescript以便在运行时访问类型级信息,最终在官方编译器中拥有plugins选项会很好😄

我现在正在度假,但下周我回来时会看看

2019 年 7 月 21 日星期日下午 5:54 Giorgio Boa [email protected]
写道:

@longlho https://github.com/longlho你创造了很多很棒的 ast
变形金刚,我需要你的帮助👍
我真的很想在 Angular 编译之前修改装饰器元数据。
我的目标是修改这个节点
Component({ selector: 'standard' ... }) 转换为 Component({ selector: 'custom'
... })
我做了一个 github repo 来测试它
https://github.com/gioboa/ng-ts-transformer 。 我认为这是可能的,但是
没有文档,我需要一些帮助。 🙏谢谢。


你收到这个是因为你被提到了。
直接回复此邮件,在 GitHub 上查看
https://github.com/microsoft/TypeScript/issues/14419?email_source=notifications&email_token=AABQM335QEEDNVT4NUICJQDQASBDXA5CNFSM4DCFER5KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD2OGIWQ#issuecomment-51356578
或使线程静音
https://github.com/notifications/unsubscribe-auth/AABQM33S5IYXB5HOZTRVVX3QASBDXANCNFSM4DCFER5A
.

我贡献了创建一个库来从没有代理的接口创建真正的模拟。 我现在建议使用 ttypescript,但如果有一个与 typescript 集成的方式会很好

我真的很想看到这个功能发生。 我很确定这是唯一介于 Typescript 和它可能带来的一些最伟大创新之间的东西。

Typescript 对前端开发做出了巨大贡献,但它也阻碍了进一步的创新……
不要破坏语义。 没有插件 ATM 不能破坏语义; 并且根本不允许使用插件 :man_shrugging: 为什么?
确实有很好的插件,但是。 每个插件都必须尊重(关键字)词标记化和 AST instation)......,在里面做一些事情真的很难。
没那么难。 这并不容易,但 babel 项目表明这是可能的。
事实上,babel 引入新的语义甚至句法短语几乎是微不足道的。

我不希望打字稿允许语义。 (当然我也不期待语法变化!)
我希望编译器在某些情况下会发生转变,比如(可能只是类型)preeval。
就像我有一个函数,比如routemessage或其他东西,编译器可以预先评估并(哦,请在第一阶段)检查正确性。

如果您阅读我的上一段很奇怪。 什么是tsx和所有 React 优点?

没有 React,没有流程,根本没有打字稿,几乎一目了然。

请。 我很理解仔细观察这一切; 但正如我们向 IE5.5+ 学习的那样; 封锁是没有出路的。

如果有什么需要改进,它仍然是布局引擎。 D.Knuth 是 50 年前设计所有缺失部件的 guenie。 为什么我们今天没有这个?? :-)
请告诉人们在 JS 邪恶中停止 CSS。

请。 开放 TS 用于语义智能; like 带有静态字符串输入的函数,为其余部分提供类型提示; 分析实际的 const 输入字符串…
一个小例子:

  • GraphQL 调用返回形状
  • 国际输入形状
  • …多得多_
    请。 无需语义更改。 一切都会按预期工作。 在构建时可能会检查更多内容。 这就是所有的人! :兔子:

我正在尝试编写 TS 转换以优化core-js导入 - 目标环境的自动填充,例如@babel/preset-env@babel/runtime ,但没有babel 。 它可以极大地帮助大部分 TS 开发人员。 但是,如果不支持自定义转换,没有额外的工具,例如ttypescript ,使用这些转换的可能性将受到严重限制,所以我不确定它是否有意义。

我一直在尝试这样的想法 - https://github.com/webschik/typescript-polyfills-generator。
我认为 Transformers API 将打开从开发链中删除babel的可能性。 我想很多开发者都不想同时使用它们,但他们仍然需要像@babel/preset-env这样的插件。

由于这个限制,我们目前推出了我们自己的自定义编译器脚本(使用 TypeScript 编译器 API)。 我们简要介绍了ttypescript ,但是根本没有从 vanilla TypeScript 编译器转移到 TypeScript 编译器扩展的兴趣。

如果 tsconfig.json 支持自定义转换器,那就太好了。 编写一个简单地解析 tsconfig,声明转换器,然后运行编译器的脚本很麻烦; 或者,更糟糕的是,实际尝试并尝试在自定义脚本中重新实现编译器的基本功能,例如监视文件。

其他人一直在呼应这种观点,但是允许轻松地将自定义转换器集成到编译器中,将减轻 TypeScript 开发团队的负担,并允许社区使用这种语言进行创新和额外的前进动力。

一个非常成功的插件生态系统的例子是无服务器框架的插件社区。 开发团队无法跟上功能开发的需求,插件提供了一种很好的方式来集成新的(可能是实验性的)功能,而无需打开 PR 或用可能或可能的功能淡化核心产品不能为更广泛的用户群提供价值。

我正在建造一个图书馆,里面有装饰器,它们对我很有用,而且我依赖它们。 前段时间我意识到装饰器使我的库不能摇树。 经过研究,我得出结论,转换器可以帮助我在编译时将这些装饰器转换为可摇树的代码。 不幸的是,我无法在我的管道中定义它们。 我希望你能尽快解决这个问题,只是想把我的 2 美分花在一个非常有帮助的用例上。

为了使 TypeScript 支持自定义转换器而无需包装程序和复杂指令,我编写了一个名为ts-patch的工具( npm github

只需安装 ts-patch(全局或本地)并运行ts-patch install来修补打字稿。 您还可以指定 typescript 安装目录和/或启用持久性,如果 TS 更新或重新安装,它会维护补丁。 (详情: ts-patch /?

补丁逻辑主要基于 ttypescript。 (非常感谢 cevek 的出色工作!)它的编写方式可以很容易地添加到 npm 包安装过程中。 也很容易取消补丁。

需要明确的是,这直接修补 typescript 本身中的相关文件,而不是包装器。 只需在依赖项安装后运行补丁,typescript 就可以准备好转换器了。

希望这可以帮助一些人!

为了使 TypeScript 支持自定义转换器而无需包装程序和复杂指令,我编写了一个名为ts-patch的工具( npm github

只需安装 ts-patch(全局或本地)并运行ts-patch install来修补打字稿。 您还可以指定 typescript 安装目录和/或启用持久性,如果 TS 更新或重新安装,它会维护补丁。 (详情: ts-patch /?

补丁逻辑主要基于 ttypescript。 (非常感谢 cevek 的出色工作!)它的编写方式可以很容易地添加到 npm 包安装过程中。 也很容易取消补丁。

需要明确的是,这直接修补 typescript 本身中的相关文件,而不是包装器。 只需在依赖项安装后运行补丁,typescript 就可以准备好转换器了。

希望这可以帮助一些人!

这可以作为公关提出来添加/讨论适当的支持吗? :)

嘿。 值得一提的是,有一个名为 fuse-box 的捆绑器,它可以很容易地添加自定义变压器。 它的 4.0 版本即将推出……所以它处于中间位置。 但总的来说,我真的很喜欢捆绑器。 也许它也可以帮助你。

https://github.com/fuse-box/fuse-box/blob/master/docs/plugins/pluginCustomTransform.md

这可以作为公关提出来添加/讨论适当的支持吗? :)

TS 团队表示他们不想将其作为原生功能提供。 他们做出这个决定的理由是有道理的!

好消息是,由于 TS 是开源的并且已经以模块化方式编译,因此 ts-patch 的行为方式与内置它时的行为方式非常相似。所以它不像一个有缺陷的逆向工程字节码补丁。

如果通过支持,您担心它被维护,我计划保持它最新并适用于所有未来版本的 TS! 我的很多商业基础设施已经依赖它。

附带说明一下,我将很快发布一个新版本,它允许将具有不同入口点的多个插件打包到一个包中,并进行一些其他优化以改进它并使其更易于使用。

写完一个插件后,我可以理解为什么 ts 团队犹豫不决——电流转换器是编译后的步骤。 如果您做任何复杂的事情并开始添加最初未绑定的新内容,您就会遇到令人讨厌的问题。 就目前而言, ts-node --compiler ttypescript foo.ts工作得很好。 我宁愿 ts 团队在不同的编译步骤处理转换器插件......或者允许重新绑定步骤。

电流互感器是一个后编译步骤。 如果您做任何复杂的事情并开始添加最初未绑定的新内容,您就会遇到令人讨厌的问题。

Transformers 可以在 TSC 编译之前或之后运行。 听起来您可能指的是检查器在修改节点后没有更新。 这实际上可以被规避,只是没有为它构建功能。 当您调用 ts.transform() 时,它不会创建一个完整的 Program 实例供您使用,因此如果您想使用检查器,您需要创建一个。 使用 CompilerHost,您可以在更改 AST 后使用修改后的文件重新加载它。

我还没有深入研究它,但看起来也可以使用“监视”功能来避免每次都重建整个程序实例。 简而言之,事实证明拥有一个更完整的插件系统实际上并_太_难,但 transform 只是缺乏其提供的上下文的支持。

@nonara我使用了带有ttypescript和 ts-loader 的转换,它们都有完整的程序入口点。 我的问题是,如果您添加一个新的导入语句,它缺少的“某些东西”并且这些新语句将从最终输出发出中删除。 @weswigham这是因为 transform 是一个绑定后的步骤。 解决方案显然是为文件制作一个全新的程序 - 但是当您处理诸如 ts-loader 之类的事情时(特别是当它处于仅转换模式并完全隐藏 webpack/bundler 文件时)这似乎令人头疼 -解析器。最后我放弃了导入,只是内联了我需要的代码

@MeirionHughes啊,好的。 在这种情况下,是的,您确实有一个 Program 实例。 ttypescript通过挂钩 createProgram 来修补生成的program的 emit 方法以包含转换器。

  • ts.emitFiles ts.transformNodes
  • ts.transformNodes可以在有或没有 Program 实例的情况下调用。 直接调用ts.transform()就没有了。

如果我理解正确,听起来您的问题也与类型和符号已经被遍历,并且它们在 AST 转换后没有更新这一事实有关。

大家好,我一直在写一本 Transformer Handbook 来整理有关 Transformer 的所有信息,并使其更容易上手。

https://github.com/madou/ts-transformer-handbook/blob/master/translations/en/transformer-handbook.md

如果你能花一点时间,会喜欢它的一些眼睛👍

这方面的现状如何?

非常喜欢 typescript,但是当您开始在静态类型和运行时 JS 之间进行互操作时,感觉尤其笨拙。 有许多社区编写的插件可以使这一点变得更好,例如https://github.com/dsherret/ts-nameofhttps://github.com/kimamula/ts-transformer-keys - 但没有一流的插件支持将它们包含在项目中感觉像是一个冒险的技术决定。 本地启用插件将允许社区在需要将它们包含在核心库中之前使用潜在的未来打字稿功能。

我认为 TypeScript 团队应该重新考虑他们的论点。 插件生态系统是推动语言向前发展的一种行之有效的方式,支持(并鼓励)实验(参见 Haskell 及其 pragma)。

其中一些实验将是狂野而疯狂的,而另一些最终会稳定下来并变得普遍。 提供在用户空间实现语言特性的能力总是好的。

总的来说,TypeScript 团队的立场看起来没有必要僵化。

还有一些转换不会改变语言,但会提供额外的信息以便于调试。

例如, babel-plugin-transform-react-jsx-source是默认反应转译预设( @babel/preset-react )的一部分。
它转变

<sometag />

进入

<sometag __source={ { fileName: 'this/file.js', lineNumber: 10 } } />

此信息允许react在开发期间提供更好的错误堆栈跟踪。

对于打字稿,虽然有一个开源转换,但没有标准的方法来实现相同的目标: https ://github.com/dropbox/ts-transform-react-jsx-source

我知道@mhegazy两次提到 TS 团队没有计划将“插件”作为 tsconfig 的一部分。 这背后的原因是什么?

你愿意接受 PR 吗? ttypescript 通过 tsconfig 处理转换器的方式非常好。

用例:

1) 为模式生成接口类型,以便可以在运行时检查它们。
2)将带有字符串的json作为文字导入,因此打字稿在分配给具有可区分联合的类型时不会出错。
3) 导入 css/yaml 和其他类似语法的对象
4) 进行动态创建正确类型的 graphql 查询
5) 将 jsx 编译为 html 字符串,以便它们可以被 innerHTML 注入
5) 将绝对导入重写为基于 tsconfig 路径的相对导入。

名单还在继续。 插件api很好。 感谢您登陆它。 拥有“tsconfig”的“插件”部分使 tsc 非常强大。 有什么大不了的吗?

你还可以做很多性能优化。 我一直在用 typescript 转换器写https://github.com/atlassian-labs/compiled-css-in-js 🤙 如果消费者不需要跳过箍来使用它,那会很酷。

亲爱的 Typescript 团队,请不要再拖后腿了 <_<

这方面的现状如何?

状态?

朋友有什么消息?

打字稿团队已经决定反对这个想法 - 如果您需要灵活性或更好的开发工具使用打字稿不是没有黑客的选择 - 改用 babel 并仅使用打字稿进行类型检查

打字稿团队已经决定反对这个想法 - 如果您需要灵活性或更好的开发工具使用打字稿不是没有黑客的选择 - 改用 babel 并仅使用打字稿进行类型检查

但是,如果我想要一些用于类型检查的技巧怎么办? 我写了一个小变压器,它有一些魔力:

type Human = {
    name: string,
    age: number
}

const isValid = check<Human>({ name: 'Carl', age: 16 }) // => true
const isValid = check<Human>({ name: 'Carl' }) // => false

函数check转化为特定的类型保护函数! 我怎样才能用 Babel 做到这一点? 目前,我应该使用 ttypescript ...

打字稿团队已经决定反对这个想法 - 如果您需要灵活性或更好的开发工具使用打字稿不是没有黑客的选择 - 改用 babel 并仅使用打字稿进行类型检查

实际上有一些关于这将在未来得到支持的讨论。 也就是说,它确实已经得到支持。 TypeScript 编译器 API 支持转换器,编写一个仅在几行代码中使用转换器的自定义编译器真的很简单。

但为了更容易,您可以使用ttypescriptts-patch

这些库并不是真正的“黑客”,因为它们没有增强编译器以添加转换器能力。 相反,它们只是将编译器 API 的现有功能公开给tsc ,使其可通过 tsconfig 使用。

@ilya-buligin 如果我正确理解您的用例,您可以声明一个环境常量

declare const check: <T>(value: unknown) => value is T;

const isValid = check<Human>({ name: 'Carl', age: 16 }) // => true

Typescript 将根据check类型定义编译代码,然后您将使用 Babel 将其替换为生成的代码。

@just-boris 如何在 Babel 中访问通用类型<T>

这个线程变得相当重复和离题。 @RyanCavanaugh也许这个线程应该被锁定,直到你有关于这个主题的任何更新。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

jbondc picture jbondc  ·  3评论

manekinekko picture manekinekko  ·  3评论

Roam-Cooper picture Roam-Cooper  ·  3评论

MartynasZilinskas picture MartynasZilinskas  ·  3评论

CyrusNajmabadi picture CyrusNajmabadi  ·  3评论