Tạo một biến toàn cục trong TypeScript


93

Trong JavaScript, tôi chỉ có thể làm điều này:

 something = 'testing';

Và sau đó trong một tệp khác:

 if (something === 'testing')

và nó sẽ somethingđược xác định (miễn là chúng được gọi theo đúng thứ tự).

Tôi dường như không thể tìm ra cách làm điều đó trong TypeScript.

Đây là những gì tôi đã thử.

Trong tệp .d.ts:

interface Window { something: string; }

Sau đó, trong tệp main.ts của tôi:

 window.something = 'testing';

sau đó trong một tệp khác:

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

Và điều này hoạt động. Nhưng tôi muốn có thể mất đi window.một phần của nó và chỉ có somethingthể là toàn cầu của tôi . Có cách nào để làm điều đó trong TypeScript không?

(Trong trường hợp ai đó quan tâm, tôi thực sự đang cố gắng thiết lập nhật ký cho ứng dụng của mình. Tôi muốn có thể gọi log.Debugtừ bất kỳ tệp nào mà không cần phải nhập và tạo đối tượng.)

Câu trả lời:


4

Được rồi, điều này có lẽ còn xấu hơn những gì bạn đã làm, nhưng dù sao thì ...

nhưng tôi cũng làm như vậy ...

Những gì bạn có thể làm để làm điều đó trong TypeScript thuần túy, là sử dụng evalchức năng như sau:

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

Và sau này bạn sẽ có thể làm

if (something === 'testing')

Đây không gì khác hơn là một vụ hack để buộc thực hiện lệnh mà TypeScript từ chối biên dịch và chúng tôi declare varđể TypeScript biên dịch phần còn lại của mã.


Điều này không hiệu quả với tôi. Tôi có eval ('myglobalvar = {};') ;. Kết quả là: Uncaught ReferenceError: myglobalvar không được xác định tại eval (eval tại <anonymous> .....). Tuy nhiên, thật thú vị nếu tôi chạy nó từ bảng điều khiển thì nó hoạt động.
— Ryan How

2
@DragonRock Tôi đã thử Chrome và FF. Vì vậy, tôi thực sự không chắc chuyện gì đang xảy ra. Dù sao đã kết thúc việc khai báo var myglobalvar; (<any> window) .myglobalvar = {}; Sau đó, tôi có thể tham chiếu nó mà không cần cửa sổ sau đó.
— Ryan How

2
.d.tsThay vào đó, điều này thực sự nên được thực hiện với một tệp định nghĩa.
— brianespinosa

2
Điều này phù hợp với tôi:export declare const SERVER = "10.1.1.26";
— xinthose.

2
Việc sử dụng evalrất không được khuyến khích, đó là lý do tại sao tôi khuyên bạn nên sử dụng giải pháp này stackoverflow.com/a/56984504/5506278
— Yaroslav Bai

62

Bên trong .d.tstệp định nghĩa

type MyGlobalFunctionType = (name: string) => void

Nếu bạn làm việc trong trình duyệt, bạn thêm thành viên vào ngữ cảnh cửa sổ của trình duyệt:

interface Window {
  myGlobalFunction: MyGlobalFunctionType
}

Ý tưởng tương tự cho NodeJS:

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

Bây giờ bạn khai báo biến gốc (thực sự sẽ tồn tại trên window hoặc global)

declare const myGlobalFunction: MyGlobalFunctionType;

Sau đó, trong một .tstệp thông thường , nhưng được nhập dưới dạng tác dụng phụ, bạn thực sự triển khai nó:

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

Và cuối cùng sử dụng nó ở nơi khác trong codebase, với:

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

myGlobalFunction("Kevin");

4
(Chỉ đưa ra nhận xét lướt qua) Nói về rất nhiều công việc để tạo một biến toàn cục đơn giản! lol
— Pytth,

6
@Benoit Tôi không nhận được phần có nội dung "nhưng được nhập dưới dạng tác dụng phụ". Ý bạn là như thế nào?. Tôi đã thử làm điều này, nhưng nó không hoạt động với tôi, bạn có thể chia sẻ một ví dụ về mã nguồn không?
— BernalCarlos

Điều này hoạt động tốt cho .tscác tệp nhưng khi tôi sử dụng window.myGlobalFunctiontrong .tsxcác tệp của mình thì không. Tôi cần thay đổi điều gì nữa ?!
— Kousha

13
Bạn đặt tệp d.ts ở đâu và làm cách nào để cấu hình TypeScript để tải nó?
— Matthias

26

globalĐây là tương lai.

Đầu tiên, các tệp TypeScript có hai loại scopes

phạm vi toàn cầu

Nếu tệp của bạn không có bất kỳ importhoặc exportdòng nào , tệp này sẽ được thực thi trong phạm vi toàn cầu mà tất cả khai báo trong đó đều hiển thị bên ngoài tệp này.

Vì vậy, chúng tôi sẽ tạo các biến toàn cục như sau:

// 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

Tất cả ma thuật đến từ var. Thay thế varbằng lethoặc constkhông hoạt động.

phạm vi mô-đun

Nếu tệp của bạn có bất kỳ importhoặc exportdòng nào , tệp này sẽ được thực thi trong phạm vi riêng của nó mà chúng tôi cần mở rộng toàn cầu bằng cách khai báo-hợp nhất .

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

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

Bạn có thể xem thêm về mô-đun trong tài liệu chính thức


Nhưng bạn sẽ làm điều này như thế nào nếu không có hack 'var'? Tôi đoán điều đó có nghĩa là, làm cách nào để tôi thực hiện việc nhập trên globalThis?
— Tom,

1
@Tom varlà cần thiết. Nhưng bạn chỉ có thể khai báo biến mà không cần khởi tạo
— Edvard chen

Làm việc cho tôi (ít nhất là bây giờ), cảm ơn rất nhiều, tôi ước câu trả lời này sẽ tăng lên. FYI: Trong trường hợp của tôi, tôi cần thêm // @ts-ignorephía trên globalThisdòng cho linter.
— David

Bạn sẽ gọi biến age trong bất kỳ tệp typecript nào?
— Ashok kumar Ganesan

18

Đây là cách tôi đã sửa nó:

Các bước:

  1. Đã khai báo một không gian tên chung, ví dụ: custom.d.ts như bên dưới:
declare global {
    namespace NodeJS {
        interface Global {
            Config: {}
        }
    }
}
export default global;
  1. Ánh xạ tệp đã tạo ở trên thành "tsconfig.json" như dưới đây:
"typeRoots": ["src/types/custom.d.ts" ]
  1. Lấy biến toàn cục đã tạo ở trên trong bất kỳ tệp nào như dưới đây:
console.log(global.config)

Ghi chú:

  1. phiên bản sắp chữ: "3.0.1".

  2. Trong trường hợp của tôi, yêu cầu là đặt biến toàn cục trước khi khởi động ứng dụng và biến phải truy cập xuyên suốt các đối tượng phụ thuộc để chúng ta có thể nhận được các thuộc tính cấu hình cần thiết.

Hi vọng điêu nay co ich!

Cảm ơn bạn


14

Tôi đã tìm thấy một cách hoạt động nếu tôi sử dụng JavaScript kết hợp với TypeScript.

logging.d.ts:

declare var log: log4javascript.Logger;

khai báo log. js :

log = null;

initalize-app.ts

import './log-declaration.js';

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

Điều này đặt nó trong phạm vi toàn cầu và TypeScript biết về nó. Vì vậy, tôi có thể sử dụng nó trong tất cả các tệp của mình.

LƯU Ý: Tôi nghĩ điều này chỉ hoạt động vì tôi đã allowJsđặt tùy chọn TypeScript thành true.

Nếu ai đó đăng một giải pháp TypeScript thuần túy, tôi sẽ chấp nhận điều đó.


1
Trong tệp initalize-app.ts của mình, bạn có thể sử dụng: declare var log: any; Sau đó, bạn không cần phải có tệp d.ts hoặc tệp js. Bạn cũng có thể thay thế bất kỳ bằng kiểu thực tế hoặc định nghĩa giao diện.
— mattferderer

5

tôi chỉ sử dụng cái này

import {globalVar} from "./globals";
declare let window:any;
window.globalVar = globalVar;

1
Điều này ném đi tất cả các loại thông tin. Cũng có thể sử dụng Javascript.
— Timmmm

3

Tôi đã dành vài giờ để tìm ra cách thích hợp để làm điều đó. Trong trường hợp của tôi, tôi đang cố gắng xác định biến "nhật ký" chung nên các bước là:

1) cấu hình của bạn tsconfig.jsonđể bao gồm các loại đã xác định của bạn ( src/typesthư mục, node_modules - tùy thuộc vào bạn):

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

2) tạo tệp src/types/global.d.tsvới nội dung sau ( không nhập! - điều này quan trọng), vui lòng thay đổi anyđể phù hợp với nhu cầu của bạn + sử dụng windowgiao diện thay vì NodeJSnếu bạn đang làm việc với trình duyệt:

/**
 * 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) bây giờ cuối cùng bạn có thể sử dụng / triển khai logkhi cần thiết:

// in one file
global.log = someCoolLogger();
// in another file
log.info('hello world');
// or if its a variable
global.log = 'INFO'

Có gì pathstrong tsconfig.json? Các tài liệu không có bất kỳ đề cập đến nó.
— tambre

Và tại sao được Globalviết hoa trong các định nghĩa, nhưng không được sử dụng trong thực tế?
— tambre

@tambre không chắc tại sao TS docs không có tài liệu đó, bạn có thể tìm thấy một số chi tiết về cấu hình này tại đây: json.schemastore.org/tsconfig và tại đây: basarat.gitbooks.io/typescript/docs/project/tsconfig.html Về Globalvới vốn - đây là cách khai báo giao diện "toàn cầu" được đặt tên trong không gian tên nodejs.
— Alexey

1

Tôi cần tạo lodash toàn cầu để sử dụng tệp .js hiện có mà tôi không thể thay đổi, chỉ yêu cầu.

Tôi thấy rằng điều này đã hoạt động:

import * as lodash from 'lodash';

(global as any)._ = lodash;

0

Như một phần bổ sung cho câu trả lời của Dima V, đây là những gì tôi đã làm để biến nó thành công việc của tôi.

// First declare the window global outside the class

declare let window: any;

// Inside the required class method

let globVarName = window.globVarName;


Người bỏ phiếu xuống có thể giải thích lý do không?
— Jonathan Cardoz

7
Đây là một giải pháp giống như dán một miếng băng đen lên đèn "kiểm tra động cơ" trên bảng điều khiển của bạn. Nó khắc phục được sự cố nhưng không đúng cách. Nó xóa sổ các loại. Nó không phải là một giải pháp tối ưu; đó là một giải pháp thay thế cũng hoạt động xung quanh mục đích chính của sắp chữ: có các loại.
— Matthias


0

Tôi đang sử dụng cái này:

interface Window {
    globalthing: any;
}

declare var globalthing: any;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookie và Chính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.