3

I usually have some server-side variables that I put into the global scope, so that I can access them from anywhere in my client side TypeScript code, e.g.:

Server in .cshtml:

<script>
  const RazorGlobals = {
    apiBaseUrl: '@Model.ApiBaseUrl'
  }
</script>

Client code:

declare const RazorGlobals: {
  apiBaseUrl: string
}

fetch(RazorGlobals.apiBaseUrl + '/myResource').then(doStuff)

At the moment I have to repeat the declare const RazorGlobals... part at the top of every file where I need to use it. I am looking for a way to define this declaration in a single place, something like this pseudocode:

globals.d.ts:

export declare const RazorGlobals: {
  apiBaseUrl: string
}

file1.ts:

import './globals'

fetch(RazorGlobals.apiBaseUrl + '/myResource').then(doStuff)

file2.ts:

import './globals'

fetch(RazorGlobals.apiBaseUrl + '/myOtherResource').then(doOtherStuff)

Is there a way to achieve something like this?

Geir Sagberg
  • 9,632
  • 8
  • 45
  • 60
  • put the d.ts file somewhere where both applications can access? – toskv Feb 21 '18 at 12:52
  • Yeah that's implied sorry. Updated the code to clarify my intention. – Geir Sagberg Feb 21 '18 at 12:56
  • he wants to add typings for a variable that is defined in the global context. Your solution would just make a variable in a module named globals. His aproach is correct he just needs to figure out how to get the compiler to include his file as well as a definition. – toskv Feb 21 '18 at 13:10
  • if the globals d.ts file is in the same folder as your project. just remove the `export` and the import statement. tsc should pick it up automatically. That being said @gilamran does have a point you should probably not just asume it will exist but actually make it part of your applications config. – toskv Feb 21 '18 at 13:14

2 Answers2

5

If you want to declare the presence of a global variable that is available everywhere all you need to is have a .d.ts file with the declaration in it.

// globals.d.ts
declare const RazorGlobals: {
  apiBaseUrl: string
}

No imports should be necessary.

toskv
  • 30,680
  • 7
  • 72
  • 74
  • 1
    This answers the exact question I was asking, so I'll mark it as the answer. With that said, I probably will do something like @gilamran suggests instead, seems like a safer approach :) – Geir Sagberg Feb 21 '18 at 13:47
  • it sure does. :) – toskv Feb 21 '18 at 13:58
3

First, don't assume global variables, there are many reasons for that.

You can have a module in the client that exposes these types, this module should take the global variable and expose it.

For example

config.ts

import { IAppConfig } from '../shared/AppConfig';
export const APP_CONFIG: IAppConfig = (window as any).RazorGlobals;

component.ts

import { APP_CONFIG } from './config';
console.log(APP_CONFIG.apiBaseUrl);

As for sharing types, you should have a shared folder between the client and server, and all the types should be there, in this example AppConfig.d.ts

Compiling the client AND the server with the same tsconfig.json is very problematic. I have a medium post on that, and an open source starter-kit.

gilamran
  • 7,090
  • 4
  • 31
  • 50