Comment définir explicitement une nouvelle propriété sur "fenêtre" dans le Tapuscrit?
-
13-12-2019 - |
Question
J'configuration de l'espace de noms global pour mes objets par la définition explicite d'un bien sur window
.
window.MyNamespace = window.MyNamespace || {};
Tapuscrit souligne MyNamespace
et se plaint que:
La propriété 'MyNamespace" n'existe pas sur la valeur de type "fenêtre" tout"
Je peux faire le code de travail en déclarant MyNamespace
comme ambiante variable et l'abandon de l' window
explicite mais je ne veux pas le faire.
declare var MyNamespace: any;
MyNamespace = MyNamespace || {};
Comment puis-je garder window
là-bas et faire Tapuscrit heureux?
Comme une note de côté je trouve ça particulièrement drôle que la Machine se plaint car il me dit que window
est de type any
qui en doute peut contenir quoi que ce soit.
La solution
Viens de trouver la réponse à cette un autre StackOverflow question réponse.
declare global {
interface Window { MyNamespace: any; }
}
window.MyNamespace = window.MyNamespace || {};
Fondamentalement, vous avez besoin de prolonger l'existant window
interface pour le dire au sujet de votre nouvelle propriété.
Autres conseils
Pour garder la dynamique, il suffit d'utiliser:
(<any>window).MyNamespace
COMME DE TAPUSCRIT ^3.4.3 CETTE SOLUTION NE FONCTIONNE PLUS
Ou...
vous pouvez simplement taper:
window['MyNamespace']
et vous ne obtenez une erreur de compilation, et il fonctionne de la même façon que la saisie d' window.MyNamespace
À l'aide de la TSX?Aucune des autres réponses ont été de travailler pour moi.
Voici ce que j'ai fait:
(window as any).MyNamespace
La accepté de répondre est ce que j'ai l'habitude d'utiliser, mais avec Tapuscrit de 0,9.* il ne fonctionne plus.La nouvelle définition de l' Window
l'interface semble remplacer complètement intégré dans la définition, à la place de l'augmentant.
J'ai commencé à le faire à la place:
interface MyWindow extends Window {
myFunction(): void;
}
declare var window: MyWindow;
Mise à JOUR: Avec Tapuscrit 0.9.5 accepté la réponse est de travailler à nouveau.
Mondiale sont "mal" :), je pense que le meilleur moyen d'avoir également la portabilité est:
D'abord de l'exportation de l'interface:(par exemple:./la coutume.de la fenêtre.ts)
export interface CustomWindow extends Window {
customAttribute: any;
}
Deuxième vous importez
import {CustomWindow} from './custom.window.ts';
Troisième cast global var fenêtre avec CustomWindow
declare let window: CustomWindow;
De cette façon, vous n'avez pas également la ligne rouge dans les différents IDE si vous utilisez existant avec les attributs de l'objet window, donc, à la fin, essayez:
window.customAttribute = 'works';
window.location.href = '/works';
Testé avec Tapuscrit 2.4.x et récent!
Si vous avez besoin d'étendre la window
objet avec un type personnalisé qui nécessite l'utilisation de import
vous pouvez utiliser la méthode suivante:
de la fenêtre.d.ts
import MyInterface from './MyInterface';
declare global {
interface Window {
propName: MyInterface
}
}
Voir 'Global d'Augmentation" dans la Déclaration de la "Fusion" de la section du Manuel: https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation
Je n'ai pas besoin de le faire très souvent, le seul cas que j'ai eu était lors de l'utilisation de Redux Devtools avec le middleware.
Je l'ai fait simplement:
const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
Ou vous pourriez faire:
let myWindow = window as any;
et puis myWindow.myProp = 'my value';
Pour ceux qui utilisent le Angulaire de la CLI c'est simple:
src/polyfills.ts
declare global {
interface Window {
myCustomFn: () => void;
}
}
mon-custom-utils.ts
window.myCustomFn = function () {
...
};
Si vous êtes à l'aide de l'Ide, il fallait aussi changer le paramètre suivant dans l'IDE avant que votre nouveau polyfills de ramassage:
> File
> Settings
> Languages & Frameworks
> TypeScript
> check 'Use TypeScript Service'.
La plupart des autres réponses ne sont pas parfaits.
- Certains d'entre eux vient de supprimer l'inférence de type pour la boutique.
- Certains autres se soucie uniquement de variable globale en tant qu'espace de noms, mais pas que/l'interface de la classe
Je rencontre également le même problème ce matin.J'ai essayé beaucoup de "solutions", mais aucun d'entre eux ne produisent aucune erreur de type absolument et permettant le déclenchement de type saut en IDE(webstorm ou vscode).
Enfin, à partir d'ici
https://github.com/Microsoft/TypeScript/issues/3180#issuecomment-102523512
, J'ai trouver une solution raisonnable joindre typings pour une variable globale qui agit comme interface/classe et de l'espace de noms à la fois.
Exemple ci-dessous:
// typings.d.ts
declare interface Window {
myNamespace?: MyNamespace & typeof MyNamespace
}
declare interface MyNamespace {
somemethod?()
}
declare namespace MyNamespace {
// ...
}
Maintenant, le code ci-dessus fusionne les typings de l'espace de noms MyNamespace
et l'interface MyNamespace
dans la variable globale myNamespace
(la propriété de la fenêtre).
Après trouver des réponses autour, je pense que cette page pourrait être utile.https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation Pas sûr au sujet de l'histoire de la déclaration de la fusion, mais elle explique pourquoi les suivantes pourraient travailler.
declare global {
interface Window { MyNamespace: any; }
}
window.MyNamespace = window.MyNamespace || {};
Voici comment le faire, si vous êtes en utilisant Tapuscrit Définition Manager!
npm install typings --global
Créer typings/custom/window.d.ts
:
interface Window {
MyNamespace: any;
}
declare var window: Window;
Installer personnalisés en tapant:
typings install file:typings/custom/window.d.ts --save --global
Fait, l'utiliser! La machine ne se plaignent plus:
window.MyNamespace = window.MyNamespace || {};
Si vous utilisez la Machine 3.x, vous pouvez être en mesure d'omettre le declare global
partie dans les autres réponses et, au lieu de simplement utiliser:
interface Window {
someValue: string
another: boolean
}
Cela a fonctionné avec moi lors de l'utilisation de la Machine 3.3, WebPack et TSLint.
Typscript ne pas effectuer typecheck sur les propriétés de la chaîne.
window["newProperty"] = customObj;
Idéalement, la variable globale scénario doit être évitée.Je l'utilise parfois pour déboguer un objet dans le navigateur de la console.
Pour la référence (c'est la bonne réponse):
À l'intérieur d'un .d.ts
fichier de définition de
type MyGlobalFunctionType = (name: string) => void
Si vous travaillez dans le navigateur, vous ajoutez des membres à la fenêtre du navigateur contexte par la réouverture de la Fenêtre de l'interface:
interface Window {
myGlobalFunction: MyGlobalFunctionType
}
Même idée pour NodeJS:
declare module NodeJS {
interface Global {
myGlobalFunction: MyGlobalFunctionType
}
}
Maintenant, vous déclarez la racine de la variable (qui vivent sur la fenêtre ou global)
declare const myGlobalFunction: MyGlobalFunctionType;
Puis dans un .ts
fichier, mais importées comme effet secondaire, vous avez réellement la mettre en œuvre:
global/* or window */.myGlobalFunction = function (name: string) {
console.log("Hey !", name);
};
Et enfin l'utiliser ailleurs dans le code, soit avec:
global/* or window */.myGlobalFunction("Kevin");
myGlobalFunction("Kevin");
Faire une interface personnalisée s'étend de la Fenêtre et ajouter votre propriété personnalisée à titre d'option.
Ensuite, laissez le customWindow que l'utilisation de l'interface personnalisée, mais apprécié, avec la fenêtre d'origine.
Il a travaillé avec l'typescript@3.1.3.
interface ICustomWindow extends Window {
MyNamespace?: any
}
const customWindow:ICustomWindow = window;
customWindow.MyNamespace = customWindow.MyNamespace {}
Pour ceux qui veulent créer une angiographie ou une propriété dynamique sur le window
objet, vous trouverez cela n'est pas possible avec la declare global
la méthode.Pour clarifier, pour ce cas d'utilisation
window[DynamicObject.key] // Element implicitly has an 'any' type because type Window has no index signature
Vous pourriez tenter de faire quelque chose comme ceci
declare global {
interface Window {
[DyanmicObject.key]: string; // error RIP
}
}
Ci-dessus l'erreur si.C'est parce que en caractères d'imprimerie, les interfaces ne sont pas bien jouer avec les propriétés calculées et lèvera une erreur de ce type
A computed property name in an interface must directly refer to a built-in symbol
Pour contourner ce problème, vous pouvez aller avec le suggèrent de casting window
pour <any>
de sorte que vous pouvez faire
(window as any)[DynamicObject.key]
Je voulais l'utiliser dans un Angle (6) de la bibliothèque d'aujourd'hui et il m'a fallu un certain temps pour que tout cela fonctionne comme prévu.
Pour ma bibliothèque à utiliser déclarations, j'ai dû utiliser l' d.ts
l'extension du fichier qui déclare les nouvelles propriétés de l'objet global.
Donc en fin de compte, le fichier à la fin quelque chose comme:
/path-to-angular-workspace/angular-workspace/projects/angular-library/src/globals.d.ts
Une fois créé, n'oubliez pas de les exposer dans votre public_api.ts
.
Qu'il a fait pour moi.Espérons que cette aide.
Vous devez d'abord déclarer la fenêtre de l'objet dans le champ d'application actuel.
Parce que tapuscrit voudrais savoir le type de l'objet.
Depuis la fenêtre de l'objet est défini quelque part d'autre, vous ne pouvez pas redéfinir.
Mais vous pouvez la déclarer comme suit:-
declare var window: any;
Ce ne sera pas redéfinir l'objet de la fenêtre ou il ne va pas créer une autre variable nom window
.
Cela signifie que la fenêtre est défini quelque part d'autre et vous êtes simplement en le référençant dans le champ d'application actuel.
Ensuite, vous pouvez vous référer à votre MyNamespace objet, simplement en:-
window.MyNamespace
Ou vous pouvez définir la propriété dans window
objet simplement:-
window.MyNamespace = MyObject
Et maintenant, le tapuscrit de ne pas se plaindre.