简体   繁体   English

全局变量作为命名空间? 为 staruml 定义环境打字稿定义

[英]global variable as a namespace ? defining ambient typescript definitions for staruml

I'm trying to define the typescript type definitions for the StarUML tool .我正在尝试为StarUML 工具定义打字稿类型定义。 I've managed to make it work for a good part of the API but I'm getting stucked on the following problem: how to make the link between a (javascript) global variable ("type" below) and a typescript namespace containing classes ?我已经设法使它适用于 API 的很大一部分,但我遇到了以下问题:如何在(javascript)全局变量(下面的“type”)和包含类的 typescript 命名空间之间建立链接?

(A) The problem to solve (一)要解决的问题

StarUML makes available a global variable type that register hundreds of class coming from unknown places. StarUML 提供了一种全局变量type ,可以注册数百个来自未知地方的类。 For instance type.Element is a class (not an Element!) as well as type.Model .例如type.Element是一个类(不是元素!)以及type.Model We use these two types as an example below.下面我们以这两种类型为例。

In javascript these classes are mostly used in statements like if (x instanceof type.Element) .在 javascript 中,这些类主要用于if (x instanceof type.Element)类的语句中。

With typescript I want to be able to define signatures like f(e : type.Element) (I would be happy to remove the type prefix but that's another story) and want to have intelli-sense for expressions like myElement._id ( _id being an attribute of the class Element .使用打字稿,我希望能够定义像f(e : type.Element)这样的签名(我很乐意删除类型前缀,但这是另一回事)并且希望对myElement._id_id是类Element的一个属性。

(B) First attempt : modeling "type" as a variable (B) 第一次尝试:将“类型”建模为变量

I first tried to define type as being a variable (as this is actually a variable) :我首先尝试将类型定义为变量(因为这实际上是一个变量):

// type.d.ts

declare class Element {
    _id: string
    // ...
}
declare class Model extends Element {
    name: string
    // ...
}

declare const type = {
    "Element" = Element,
    "Model" = Model
    // ...
}

This does not work as this produce the following error: S1254: A 'const' initializer in an ambient context must be a string or numeric literal or literal enum reference .这不起作用,因为这会产生以下错误: S1254: A 'const' initializer in an ambient context must be a string or numeric literal or literal enum reference I mention this solution because it makes it clear what type is all about : a register that gives for each class name (string), the class itself.我提到这个解决方案是因为它清楚地说明了type是什么:一个为每个类名(字符串)提供的寄存器,类本身。 The classes are defined somewhere else in an unknown places.这些类是在未知位置的其他地方定义的。

(C) Second attempt : modeling "type" as a Namespace. (C) 第二次尝试:将“类型”建模为命名空间。

Ater reading the typescript documentation, and after various trials I came up with the following typescript file types.d.ts (That might be were I'm wrong).在阅读打字稿文档后,经过各种试验,我想出了以下打字稿文件types.d.ts (那可能是我错了)。

// types.ts
export namespace type {
    class Element {
        _id: string
        // ...
    }
    class Model extends Element {
        name: string
    }
    // ...
}

(D) Client code (D) 客户代码

Below is an example code ( main.ts ) that use this API definition.下面是使用此 API 定义的示例代码 ( main.ts )。 To simplify the file type.d.ts and main.ts are at both at the top level.为了简化文件type.d.tsmain.ts都在顶层。

// (1)     /// <reference path="./types.d.ts" />
// (2)     import {type} from "./types"
// (3)     declare var type

function hello(m: type.Element): void {
    console.log("    hello: (" + e._id + ')')
}
console.log(type)
console.log(type.Element)

I don't manage to "make it work" I've tried various combinations uncommenting some of the first 3 lines (see below).我没有设法“让它工作”我尝试了各种组合,取消了前 3 行中的一些(见下文)。

(D.2) My expectations : (D.2) 我的期望:

  • (a) the type in the function hello should be defined properly (typescript) (a) function hello中的类型应正确定义(打字稿)
  • (b) the intelli sense should work on the next line e._id (typescript) (b) 智能感知应该在下一行e._id (typescript) 上起作用
  • (c) the last line should display the type.Element class (javascript) (c) 最后一行应该显示type.Element类 (javascript)

I can't make it works all at the same time irrespective of the "importing" first lines.无论“导入”第一行如何,我都无法让它同时工作。

(D.3) What I got : (D.3) 我得到了什么:

  • (1) I didn't manage to make line (1) /// <reference ... "work" at all. (1) 我没有设法使第 (1) 行/// <reference ... “工作”。 I also tried solutions provided in forums such as using tsconfig with typeRoots and paths .我还尝试了论坛中提供的解决方案,例如将tsconfigtypeRootspaths一起使用。 I don't know if the solution should come from there.我不知道解决方案是否应该来自那里。

  • (2) import {type} ... is ok for the namespace but then line console.log(type.element) return undefined at runtime. (2) import {type} ...对于命名空间是可以的,但是行console.log(type.element)在运行时返回 undefined。

  • (3) declare var type makes the javascript code run ok but in conflict with (2). (3) declare var type使 javascript 代码运行正常但与 (2) 冲突。

When (2) and (3) are present at the same time, a typescript error is generated because of conflict between type as namespace and type as variable.当 (2) 和 (3) 同时存在时,由于type as namespace 和type as variable 之间的冲突,会产生 typescript 错误。

(D.4) What is the solution ? (D.4) 解决方案是什么?

After reading the typescript documentation and some other blogs I'm still confused.在阅读了打字稿文档和其他一些博客后,我仍然感到困惑。 I don't know if the problem is in my approach (C), "modeling the variable type" as a namespace, or I don't know how to call this namespace/variable at compilation/runtime.我不知道问题是否出在我的方法(C)中,“将变量类型建模”为命名空间,或者我不知道如何在编译/运行时调用此命名空间/变量。

Any information or pointer to the information would be very very much welcomed !非常欢迎任何信息或指向该信息的指针! Thanks for all.谢谢大家。

Caveat: I'm only middling-good at TypeScript, and less so with regard to .d.ts files.警告:我在 TypeScript 方面只是中等水平,而在.d.ts文件方面则不太好。 But this worked locally and seems to match up with the documentation , in particular this example .但这在本地工作,并且似乎与文档相匹配,特别是这个示例

A .d.ts file defines ambient declarations, you don't use export in it (as far as I know), you just declare things in it, since the purpose is to declare things that already exist (in your case, because of the SmartUML library creating that type global and its properties at runtime).一个.d.ts文件定义环境声明,你不要在其中使用export (据我所知),你只是在其中声明东西,因为目的是声明已经存在的东西(在你的情况下,因为SmartUML 库在运行时创建该type全局及其属性)。

So in your .d.ts file, you declare a namespace containing those classes:因此,在您的.d.ts文件中,您声明一个包含这些类的命名空间:

/**
 * SmartUML namespace global.
 */
declare namespace type {
    /**
     * SmartUML `Element` class.
     */
    class Element {
        /**
         * The ID fo the element.
         */
        _id: string;
        // ...
    }
    /**
     * SmartUML `Model` class.
     */
    class Model extends Element {
        /**
         * The name of the model.
         */
        name: string;
        // ...
    }
    // ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM