Erstellen Sie eine globale Variable in TypeScript

85

In JavaScript kann ich das einfach so machen:

 something = 'testing';

Und dann in einer anderen Datei:

 if (something === 'testing')

und es wird somethingdefiniert worden sein (solange sie in der richtigen Reihenfolge aufgerufen wurden).

Ich kann anscheinend nicht herausfinden, wie das in TypeScript geht.

Das habe ich versucht.

In einer .d.ts-Datei:

interface Window { something: string; }

Dann in meiner main.ts-Datei:

 window.something = 'testing';

dann in einer anderen Datei:

 if (window.something  === 'testing')

Und das funktioniert. Aber ich möchte in der Lage sein, den window.Teil davon zu verlieren und einfach somethingglobal zu sein. Gibt es eine Möglichkeit, dies in TypeScript zu tun?

(Falls jemand interessiert ist, versuche ich wirklich, meine Protokollierung für meine Anwendung einzurichten. Ich möchte log.Debugaus jeder Datei aufrufen können, ohne Objekte importieren und erstellen zu müssen.)

Vaccano
quelle

Antworten:

4

Okay, das ist wahrscheinlich noch hässlicher als das, was du getan hast, aber trotzdem ...

aber ich mache das gleiche so ...

Um dies in reinem TypeScript zu tun, können Sie die folgende evalFunktion verwenden:

declare var something: string;
eval("something = 'testing';")

Und später können Sie es tun

if (something === 'testing')

Dies ist nichts weiter als ein Hack, um die Ausführung der Anweisung zu erzwingen, ohne dass TypeScript die Kompilierung verweigert, und wir declare varfür TypeScript, um den Rest des Codes zu kompilieren.

tforgione
quelle
Das funktioniert bei mir nicht. Ich habe eval ('myglobalvar = {};');. Dies führt zu: Ungefangener Referenzfehler: myglobalvar ist bei eval nicht definiert (eval bei <anonymous> .....). Komischerweise funktioniert es, wenn ich es von der Konsole aus starte.
Ryan How
2
@DragonRock Ich habe Chrome und FF ausprobiert. Ich bin mir also nicht sicher, was los war. Wie auch immer, deklarieren Sie var myglobalvar; (<jedes> Fenster) .myglobalvar = {}; Dann kann ich danach ohne Fenster darauf verweisen.
Ryan How
2
Dies sollte wirklich stattdessen mit einer .d.tsDefinitionsdatei erfolgen.
Brianespinosa
2
Das funktioniert bei mir:export declare const SERVER = "10.1.1.26";
xinthose
1
Von der Verwendung evalwird dringend abgeraten, daher empfehle ich die Verwendung dieser Lösung stackoverflow.com/a/56984504/5506278
Yaroslav Bai
60

In einer .d.tsDefinitionsdatei

type MyGlobalFunctionType = (name: string) => void

Wenn Sie im Browser arbeiten, fügen Sie dem Fensterkontext des Browsers Mitglieder hinzu:

interface Window {
  myGlobalFunction: MyGlobalFunctionType
}

Gleiche Idee für NodeJS:

declare module NodeJS {
  interface Global {
    myGlobalFunction: MyGlobalFunctionType
  }
}

Jetzt deklarieren Sie die Stammvariable (die tatsächlich im Fenster oder global lebt).

declare const myGlobalFunction: MyGlobalFunctionType;

Dann .tsimplementieren Sie es in einer regulären Datei, die jedoch als Nebeneffekt importiert wurde:

global/* or window */.myGlobalFunction = function (name: string) {
  console.log("Hey !", name);
};

Und schließlich verwenden Sie es an anderer Stelle in der Codebasis, entweder mit:

global/* or window */.myGlobalFunction("Kevin");

myGlobalFunction("Kevin");
Benoit B.
quelle
4
(Machen Sie nur einen kurzen Kommentar) Sprechen Sie über viel Arbeit, um eine einfache globale Variable zu erstellen! lol
Pytth
6
@ Benoit Ich bekomme nicht den Teil, der sagt "aber als Nebeneffekt importiert". Was meinst du damit?. Ich habe versucht, dies zu tun, aber es funktioniert bei mir nicht. Können Sie ein Quellcode-Beispiel freigeben?
BernalCarlos
Dies funktioniert gut für .tsDateien, aber wenn ich es window.myGlobalFunctionin meinen .tsxDateien verwende, funktioniert es nicht. Was muss ich noch ändern?!
Kousha
11
Wo legen Sie die Datei d.ts ab und wie konfigurieren Sie TypeScript zum Laden?
Matthias
22

globalThis ist die Zukunft.

Erstens gibt es bei TypeScript-Dateien zwei Arten von scopes

globaler Geltungsbereich

Wenn Ihre Datei keine importoder keine exportZeile enthält , wird diese Datei im globalen Bereich ausgeführt sodass alle darin enthaltenen Deklarationen außerhalb dieser Datei sichtbar sind.

Wir würden also globale Variablen wie folgt erstellen:

// xx.d.ts
declare var age: number

// or 
// xx.ts
// with or without declare keyword
var age: number

// other.ts
globalThis.age = 18 // no error

Alle Magie kommt von var. Ersetzen vardurch letoder constfunktioniert nicht.

Modulumfang

Wenn Ihre Datei eine importoder eine exportZeile enthält , wird diese Datei in ihrem eigenen Bereich ausgeführt, den wir durch Zusammenführen von Deklarationen global erweitern müssen .

// xx[.d].ts
declare global {
  var age: number;
}

// other.ts
globalThis.age = 18 // no error

Weitere Informationen zum Modul finden Sie in den offiziellen Dokumenten

edvard chen
quelle
Aber wie würden Sie dies ohne den 'var'-Hack tun? Ich denke, das bedeutet, wie würde ich Augmentation auf globalThis durchführen?
Tom
1
@ Tom varist notwendig. Aber Sie können einfach Variable ohne Initialisierung deklarieren
Edvard Chen
Ich habe für mich gearbeitet (zumindest für den Moment). Vielen Dank, ich wünschte, diese Antwort würde nach oben gehen. Zu Ihrer Information: In meinem Fall musste ich // @ts-ignoreüber der globalThisLinie für den Linter hinzufügen .
David
16

So habe ich es behoben:

Schritte:

  1. Deklarierte einen globalen Namespace, z. B. custom.d.ts wie folgt:
declare global {
    namespace NodeJS {
        interface Global {
            Config: {}
        }
    }
}
export default global;
  1. Ordnen Sie die oben erstellte Datei wie folgt in "tsconfig.json" zu:
"typeRoots": ["src/types/custom.d.ts" ]
  1. Rufen Sie die oben erstellte globale Variable in einer der folgenden Dateien ab:
console.log(global.config)

Hinweis:

  1. Typoskript-Version: "3.0.1".

  2. In meinem Fall bestand die Anforderung darin, die globale Variable festzulegen, bevor die Anwendung gestartet wird, und die Variable sollte auf alle abhängigen Objekte zugreifen, damit wir die erforderlichen Konfigurationseigenschaften erhalten können.

Hoffe das hilft!

Danke dir

Vikash Kumar Choudhary
quelle
14

Ich habe einen Weg gefunden, der funktioniert, wenn ich JavaScript in Kombination mit TypeScript verwende.

logging.d.ts:

declare var log: log4javascript.Logger;

Protokolldeklaration. js :

log = null;

initalize-app.ts

import './log-declaration.js';

// Call stuff to actually setup log.  
// Similar to this:
log = functionToSetupLog();

Dies versetzt es in den globalen Bereich und TypeScript weiß davon. So kann ich es in allen meinen Dateien verwenden.

HINWEIS: Ich denke, dies funktioniert nur, weil ich die allowJsTypeScript-Option auf true gesetzt habe.

Wenn jemand eine reine TypeScript-Lösung veröffentlicht, werde ich das akzeptieren.

Vaccano
quelle
1
In Ihrer Datei initalize-app.ts können Sie Folgendes verwenden: declare var log: any; Dann benötigen Sie weder die Datei d.ts noch die Datei js. Sie können jeden auch durch einen tatsächlichen Typ oder eine Schnittstellendefinition ersetzen.
Mattferderer
5

Ich benutze nur das

import {globalVar} from "./globals";
declare let window:any;
window.globalVar = globalVar;
Dima V.
quelle
1
Dies wirft alle Typinformationen weg. Kann auch Javascript verwenden.
Timmmm
2

Ich habe ein paar Stunden damit verbracht, herauszufinden, wie ich es richtig machen kann. In meinem Fall versuche ich, eine globale "Protokoll" -Variable zu definieren, also waren die Schritte:

1) Konfigurieren Sie Ihre tsconfig.json, um Ihre definierten Typen src/typeseinzuschließen ( Ordner, Knotenmodule - liegt bei Ihnen):

...other stuff...
"paths": {
  "*": ["node_modules/*", "src/types/*"]
}

2) Erstellen Sie eine Datei src/types/global.d.tsmit folgendem Inhalt ( keine Importe! - das ist wichtig). Sie können sie jederzeit anyan Ihre Bedürfnisse anpassen und die windowBenutzeroberfläche verwenden, anstatt NodeJSmit dem Browser zu arbeiten:

/**
 * IMPORTANT - do not use imports in this file!
 * It will break global definition.
 */
declare namespace NodeJS {
    export interface Global {
        log: any;
    }
}

declare var log: any;

3) Jetzt können Sie endlich verwenden / implementieren, logwo es benötigt wird:

// in one file
global.log = someCoolLogger();
// in another file
log.info('hello world');
// or if its a variable
global.log = 'INFO'
Alexey
quelle
Was ist pathsin tsconfig.json? Die Dokumente haben keine Erwähnung.
Tambre
Und warum wird Globalin den Definitionen groß geschrieben, aber nicht in der tatsächlichen Verwendung?
Tambre
@tambre nicht sicher, warum TS-Dokumente es nicht dokumentiert haben, finden Sie einige Details zu dieser Konfiguration hier: json.schemastore.org/tsconfig und hier: basarat.gitbooks.io/typescript/docs/project/tsconfig.html Bezüglich Globalmit Kapital - so wird die "globale" Schnittstellendeklaration im Namespace von nodejs benannt.
Alexey
0

Als Ergänzung zu Dima Vs Antwort habe ich dies getan, um diese Arbeit für mich zu machen.

// First declare the window global outside the class

declare let window: any;

// Inside the required class method

let globVarName = window.globVarName;

Jonathan Cardoz
quelle
Kann die Person, die dies abgelehnt hat, den Grund erklären?
Jonathan Cardoz
7
Nun, dies ist eine Lösung, wie Sie ein Stück schwarzes Klebeband über Ihre "Check Engine" -Lampe auf Ihrem Armaturenbrett kleben. Es behebt das Problem, aber nicht auf die richtige Weise. Es löscht Typen aus. Es ist keine optimale Lösung; Es ist eine Problemumgehung, die auch den Hauptzweck von Typoskript umgeht: Typen zu haben.
Matthias
0

Ich musste lodash global machen, um eine vorhandene .js-Datei zu verwenden, die ich nicht ändern konnte, sondern nur benötigte.

Ich fand, dass dies funktionierte:

import * as lodash from 'lodash';

(global as any)._ = lodash;
TrueWill
quelle
0

Dies funktioniert für mich, wie in diesem Thread beschrieben :

declare let something: string;
something = 'foo';
Nacho Coloma
quelle