Je configure des espaces de noms globaux pour mes objets en définissant explicitement une propriété sur window
.
window.MyNamespace = window.MyNamespace || {};
TypeScript souligne MyNamespace
et se plaint de ce qui suit:
La propriété 'MyNamespace' n'existe pas sur la valeur de type 'window' tout"
Je peux faire fonctionner le code en déclarant MyNamespace
en tant que variable ambiante et en supprimant le caractère explicite de window
mais je ne veux pas le faire.
declare var MyNamespace: any;
MyNamespace = MyNamespace || {};
Comment puis-je conserver window
et rendre TypeScript heureux?
En remarque, je trouve particulièrement drôle que TypeScript se plaint, car il me dit que window
est de type any
et qu'il peut certainement contenir n'importe quoi.
Je viens de trouver la réponse à ceci dans la réponse à une autre question StackOverflow .
declare global {
interface Window { MyNamespace: any; }
}
window.MyNamespace = window.MyNamespace || {};
Fondamentalement, vous devez étendre l’interface window
existante pour la renseigner sur votre nouvelle propriété.
Pour rester dynamique, utilisez simplement:
(<any>window).MyNamespace
Ou...
vous pouvez simplement taper:
window['MyNamespace']
et vous n'obtiendrez pas d'erreur de compilation et cela fonctionne de la même manière que si vous tapiez window.MyNamespace
Vous utilisez TSX? Aucune des autres réponses ne fonctionnait pour moi.
Voici ce que j'ai fait:
(window as any).MyNamespace
La réponse acceptée est celle que j’avais l'habitude d'utiliser, mais avec TypeScript 0.9. * Cela ne fonctionne plus. La nouvelle définition de l'interface Window
semble remplacer complètement la définition intégrée, au lieu de l'augmenter.
J'ai pris à faire cela à la place:
interface MyWindow extends Window {
myFunction(): void;
}
declare var window: MyWindow;
UPDATE: Avec TypeScript 0.9.5, la réponse acceptée fonctionne à nouveau.
Si vous devez étendre l'objet window
avec un type personnalisé nécessitant l'utilisation de import
, vous pouvez utiliser la méthode suivante:
window.d.ts
import MyInterface from './MyInterface';
declare global {
interface Window {
propName: MyInterface
}
}
Voir «Augmentation globale» dans la section «Déclaration» du manuel: https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation
Global are "evil" :), je pense que la meilleure façon d’avoir la portabilité est:
D'abord, vous exportez l'interface: (par exemple: ./custom.window.ts)
export interface CustomWindow extends Window {
customAttribute: any;
}
Deuxièmement, vous importez
import {CustomWindow} from './custom.window.ts';
Troisième fenêtre var de distribution globale avec CustomWindow
declare let window: CustomWindow;
De cette manière, vous n'avez pas non plus de ligne rouge dans différents IDE si vous utilisez des attributs existants d'un objet window, aussi essayez-vous à la fin:
window.customAttribute = 'works';
window.location.href = '/works';
Testé avec TypeScript 2.4.x
Je n'ai pas besoin de le faire très souvent, le seul cas que j'ai eu concernait l'utilisation de Redux Devtools avec un middleware.
J'ai simplement fait:
const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
Ou tu pourrais faire:
let myWindow = window as any;
et ensuite myWindow.myProp = 'my value';
La plupart des autres réponses ne sont pas parfaites.
Je rencontre aussi le même problème ce matin. J'ai essayé autant de "solutions" sur SO, mais aucune d'entre elles ne produisait absolument d'erreur de type et permettait de déclencher le saut de type dans IDE (webstorm ou vscode).
Enfin, d'ici
https://github.com/Microsoft/TypeScript/issues/3180#issuecomment-102523512
, Je trouve une solution raisonnable à attach typings pour la variable globale qui fait office d’interface/classe et d’espace de nom.
Exemple est ci-dessous:
// typings.d.ts
declare interface Window {
myNamespace?: MyNamespace & typeof MyNamespace
}
declare interface MyNamespace {
somemethod?()
}
declare namespace MyNamespace {
// ...
}
Désormais, le code ci-dessus fusionne les typages d'espace de nom MyNamespace
et d'interface MyNamespace
dans la variable globale myNamespace
(la propriété de window).
Si vous utilisez le CLI angulaire c'est vraiment simple:
src/polyfills.ts
declare global {
interface Window {
myCustomFn: () => void;
}
}
my-custom-utils.ts
window.myCustomFn = function () {
...
};
Si vous utilisez IntelliJ, vous deviez également modifier le paramètre suivant dans IDE avant la reprise de votre nouveau remplissage multiple:
> File
> Settings
> Languages & Frameworks
> TypeScript
> check 'Use TypeScript Service'.
Voici comment procéder, si vous utilisez TypeScript Definition Manager!
npm install typings --global
Créer typings/custom/window.d.ts
:
interface Window {
MyNamespace: any;
}
declare var window: Window;
Installez votre saisie personnalisée:
typings install file:typings/custom/window.d.ts --save --global
Fait, utilise it! TypeScript ne se plaindra plus:
window.MyNamespace = window.MyNamespace || {};
Après avoir trouvé des réponses, je pense que cette page pourrait être utile . https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation historique de la fusion des déclarations, mais explique pourquoi ce qui suit pourrait fonctionner.
declare global {
interface Window { MyNamespace: any; }
}
window.MyNamespace = window.MyNamespace || {};
Pour référence (c'est la bonne réponse):
Dans un fichier de définition .d.ts
type MyGlobalFunctionType = (name: string) => void
Si vous travaillez dans le navigateur, vous ajoutez des membres au contexte de la fenêtre du navigateur en rouvrant l'interface de Windows:
interface Window {
myGlobalFunction: MyGlobalFunctionType
}
Même idée pour NodeJS:
declare module NodeJS {
interface Global {
myGlobalFunction: MyGlobalFunctionType
}
}
Maintenant, vous déclarez la variable racine (qui vivra réellement sur window ou global)
declare const myGlobalFunction: MyGlobalFunctionType;
Ensuite, dans un fichier .ts
normal, mais importé comme effet secondaire, vous l'implémentez:
global/* or window */.myGlobalFunction = function (name: string) {
console.log("Hey !", name);
};
Et enfin, utilisez-le ailleurs dans la base de code, avec soit:
global/* or window */.myGlobalFunction("Kevin");
myGlobalFunction("Kevin");
Typescript n'effectue pas de vérification sur les propriétés de chaîne.
window["newProperty"] = customObj;
Idéalement, le scénario de variable globale devrait être évité. Je l'utilise parfois pour déboguer un objet dans la console du navigateur.
Je voulais utiliser cela dans une bibliothèque Angular (6) aujourd'hui et il m'a fallu un certain temps pour que cela fonctionne comme prévu.
Pour que ma bibliothèque utilise des déclarations, je devais utiliser l'extension d.ts
pour le fichier qui déclare les nouvelles propriétés de l'objet global.
En fin de compte, le fichier s'est retrouvé avec quelque chose comme:
/path-to-angular-workspace/angular-workspace/projects/angular-library/src/globals.d.ts
Une fois créé, n'oubliez pas de l'exposer dans votre public_api.ts
.
Cela l'a fait pour moi. J'espère que cela t'aides.
Pour ceux qui souhaitent définir une propriété calculée ou dynamique sur l'objet window
, vous constaterez que c'est impossible avec la méthode declare global
. Pour clarifier ce cas d'utilisation
window[DynamicObject.key] // Element implicitly has an 'any' type because type Window has no index signature
Vous pourriez essayer de faire quelque chose comme ça
declare global {
interface Window {
[DyanmicObject.key]: string; // error RIP
}
}
Ce qui précède sera une erreur cependant. En effet, dans TypeScript, les interfaces ne fonctionnent pas bien avec les propriétés calculées et génèrent une erreur telle que
A computed property name in an interface must directly refer to a built-in symbol
Pour résoudre ce problème, vous pouvez suggérer de convertir window
en <any>
pour pouvoir le faire.
(window as any)[DynamicObject.key]
Créez une interface personnalisée qui étend la fenêtre et ajoutez votre propriété personnalisée comme facultative.
Ensuite, laissez la fenêtre customWindow qui utilise l'interface personnalisée, mais qui est évaluée avec la fenêtre d'origine.
Cela a fonctionné avec le [email protected].
interface ICustomWindow extends Window {
MyNamespace?: any
}
const customWindow:ICustomWindow = window;
customWindow.MyNamespace = customWindow.MyNamespace {}
Si vous utilisez TypeScript 3.x, vous pourrez peut-être omettre la partie declare global
dans les autres réponses et utiliser simplement:
interface Window {
someValue: string
another: boolean
}
Cela a fonctionné avec moi lors de l'utilisation de TypeScript 3.3, WebPack et TSLint.
Tout d'abord, vous devez déclarer l'objet window dans la portée actuelle.
Parce que TypeScript aimerait connaître le type de l'objet.
Comme l’objet window est défini ailleurs, vous ne pouvez pas le redéfinir.
Mais vous pouvez le déclarer comme suit: -
declare var window: any;
Cela ne va pas redéfinir l'objet window ni créer une autre variable avec le nom window
.
Cela signifie que la fenêtre est définie ailleurs et que vous ne faites que la référencer dans la portée actuelle.
Ensuite, vous pouvez faire référence à votre objet MyNamespace simplement par: -
window.MyNamespace
Ou vous pouvez définir la nouvelle propriété sur l'objet window
simplement en: -
window.MyNamespace = MyObject
Et maintenant, le TypeScript ne va pas se plaindre.