TypeScript'teki `pencere` üzerinde açıkça yeni bir özelliği nasıl ayarlarsınız?


621

Açıkça bir özellik ayarlayarak nesnelerim için genel ad alanları oluşturdum window.

window.MyNamespace = window.MyNamespace || {};

TypeScript aşağıdakilerin altını çizer MyNamespaceve şikayet eder:

'Window' any 'türünün değerinde' MyNamespace 'özelliği yok

Ben MyNamespacebir ortam değişkeni olarak ilan ve açıklık bırakarak kod çalışması yapabilirsiniz windowama bunu yapmak istemiyorum.

declare var MyNamespace: any;

MyNamespace = MyNamespace || {};

Nasıl tutabilir windoworada ve typescript mutlu edecek mi?

Bir yan not olarak, TypeScript'in şikayet etmesini özellikle komik buluyorum çünkü bana kesinlikle bir şey içerebilecek windowtipte olduğunu söylüyor any.


bkz. Bağlantı
MHS

Yanıtlar:


692

Bunun cevabını başka bir StackOverflow sorusunun cevabında buldum .

declare global {
    interface Window { MyNamespace: any; }
}

window.MyNamespace = window.MyNamespace || {};

Temel olarak window, yeni mülkünüz hakkında bilgi vermek için mevcut arayüzü genişletmeniz gerekir .


12
Pencerede büyük W harfini not edin. Bu beni harekete geçirdi.
ajm

2
Bunu tsc 1.0.1.0 ile derleyemedim. Blake Mitchell'in yanıtı benim için işe yaradı.
Pat

43
Bunun yalnızca ayrı bir .d.tsdosyada bildirildiğinde işe yaradığını unutmayın . .tsİçe aktarma ve dışa aktarma kullanan bir dosyada kullanıldığında çalışmaz . Bu cevaba bakınız .
cdauth

36
declare global { interface Window { ... } }Typescript 2.5.2 ile çalışır, gerek .d.tsdosyası yukarıda belirtildiği gibi
tanguy_k

2
İlk daktiloda söyledim: error TS1234: An ambient module declaration is only allowed at the top level in a file.Dosyanın en üstüne koyduğumda, bu hatayı düzeltti, bu yüzden bunu da yapmanız gerekebilir.
Zelphir Kaltstahl

397

Dinamik tutmak için şunu kullanın:

(<any>window).MyNamespace

9
Herhangi bir fikir bir tsx dosyasında nasıl?
geliştirmem

2
@martin: <any> bunu açıkça ortaya koyuyor, bu yüzden iyi çalışıyor, inanıyorum. Diğer: React veya başka bir JSX ortamıyla (TSX sözdizimiyle sonuçlanan) Typcript kullanıyorsanız, asbunun yerine kullanmanız gerekir <>. Aşağıdaki @ david-boyd cevabına bakınız .
Don

31
Kullanmak zorunda kaldım (herhangi bir pencere) .MyNamespace
Arsalan Ahmad

Benzer şekilde this-return (<any> this)['something in scope']
HankCa

1
Bu satırda tslint'i devre dışı bırakmak zorunda kaldım/* tslint:disable */
Michael Yagudaev

197

TYPESCRIPT ^ 3.4.3'DEN BU ÇÖZÜM ARTIK DAHA ÇALIŞMAZ

Veya...

sadece şunu yazabilirsiniz:

window['MyNamespace']

ve bir derleme hatası almayacaksınız ve yazmakla aynı şekilde çalışıyor window.MyNamespace


15
ama muhtemelen bir tslint hatası alacaksınız ... Tabii varsa
smnbbrv

69
Bu, TypeScript'in arkasındaki tüm fikir olan güçlü yazma karşısında tamamen uçuyor.
d512

18
@ user1334007 globals kullanarak da yapar. Ancak, bazı eski kodlar bunu gerektirir.
nathancahill

3
@Ramesh window['MyNamespace']()(sadece parantez ekleyin)
iBaff

6
"Bu, TypeScript'in arkasındaki tüm fikir olan güçlü yazma karşısında tamamen uçuyor." İYİ!
Cody

188

TSX mi kullanıyorsunuz? Diğer cevapların hiçbiri benim için işe yaramıyordu.

İşte yaptım:

(window as any).MyNamespace


44
TSX kullanımı dışında aynıdır, çünkü <any>türler cast değil, JSX olarak yorumlanır.
Jake Boone

1
Teşekkürler @David, bu yeni React Uygulaması Oluştur ve daktilo sürümü ile bir cazibe gibi çalıştı, Daha önce bu çalışıyordu: (<any> penceresi) .MyNamespace, ama şimdi yeni daktilo sürümü 3.5.x kırılıyor.
Jignesh Raval

pencere gibi? Öyleyse neden daktiloyu kullanasınız? Sadece Javascript x kullanın)
MarcoLe

71

Kabul ettiğim cevap eskiden kullandığım şeydi, ancak TypeScript 0.9. * İle artık çalışmıyor. WindowArayüzün yeni tanımı , genişletmek yerine yerleşik tanımın yerini alıyor gibi görünüyor.

Bunun yerine bunu yaptım:

interface MyWindow extends Window {
    myFunction(): void;
}

declare var window: MyWindow;

GÜNCELLEME: TypeScript 0.9.5 ile kabul edilen cevap tekrar çalışır.


2
Bu, TypeScript 2.0.8 tarafından kullanılan modüllerle de çalışır. Örnek: export default class MyClass{ foo(){ ... } ... } interface MyWindow extends Window{ mc: MyClass } declare var window: MyWindow window.mc = new MyClass() Ardından foo () öğesini örneğin Chrome Dev Tools konsolundanmc.foo()
Martin Majewski

Eğer bir şeyi küresel olarak ilan etmek istemiyorsanız, bu çok hoş bir cevaptır. Diğer tarafta, ihtiyacınız olan declare var...her dosyayı aramanız gerekir.
Puce

Artı bu yaklaşım için bir tane çünkü bu durumda monorepo küresel penceresini genişleten diğer paketler ile çatışma yok.
Dmitrii Sorin

Teşekkür ederim! En iyi cevap IMO. Vanilya penceresi olmadığıWindow için basitçe geçersiz kılınmamalıdır. Sadece tip kontrolünü atlatmak veya TS'yi kandırmaya çalışmak da bunu yapmanın yolu değil.
Rutger Willems

Ne yazık ki TS 3.6'dan itibaren çalışmaz
Jacob Soderlund

65

Küresel "kötü" :), ben de taşınabilirlik için en iyi yolu olduğunu düşünüyorum:

Önce arayüzü dışa aktarın: (örneğin: ./custom.window.ts)

export interface CustomWindow extends Window {
    customAttribute: any;
}

İkincisi içe aktardığınızda

import {CustomWindow} from './custom.window.ts';

CustomWindow ile üçüncü döküm global değişken penceresi

declare let window: CustomWindow;

Bu şekilde, pencere nesnesinin varolan öznitelikleriyle kullanıyorsanız, farklı IDE'de kırmızı çizginiz olmaz, bu nedenle sonunda şunu deneyin:

window.customAttribute = 'works';
window.location.href = '/works';

Typcript 2.4.x ve en yenisi ile test edildi!


1
küresellerin neden kötü olduğu üzerine genişlemek isteyebilirsiniz. Bizim durumumuzda, pencere nesnesinde standart olmayan bir API kullanıyoruz. Şimdilik poli dolgulu. Gerçekten kötülük mü?
Mathijs Segers

1
@MathijsSegers özellikle sizin durumunuzu bilmiyorum ama .. globaller hakkında kötü sadece javascript ile ilgili değil .. her dilde .. bazı nedenleri vardır: - İyi tasarım deseni uygulayamazsınız - Bellek ve performans sorunu (Sen onları her yerde var, Dize Nesnesi bir şey eklemek deneyin ve yeni Dize yaptığınızda ne olacağını görmek) - İsim çarpışma kodunda yan etkisi neden .. (özellikle zaman uyumsuz doğa javascript üzerinde) devam edebilirim ama ben görüntü dinlenme...
onalbi

1
@onabi Kelimenin tam anlamıyla tarayıcının bir özelliği hakkında konuşuyorum. Tarayıcı olduğu için küresel olarak kullanılabilir. Gerçekten küresel tanımlara gitmenin hala yanlış olduğunu mu düşünüyorsunuz? Yani Ponyfill'leri uygulayabiliriz, ancak bu aslında özelliği destekleyen tarayıcıları şişirirdi (örn. Tam ekran api). Bütün küresellerin kötü bir kişi olduğuna inanmıyorum dedi.
Mathijs Segers

2
@MathijsSegers Bence küresel değişken kullanılabilir veya kullanılan mümkün olduğunca değiştirilmelidir kaçının .. tarayıcı var beri pencere mevcuttur doğrudur ama aynı zamanda her zaman mutasyonda doğrudur .. yani eğer şimdi tanımlamak eğer window.feature = 'Özellik'; ve bu kod üzerinde büyük bir şekilde kullanılır .. window.feature tüm özellikleri bu özelliği geçersiz kılan tarayıcılar tarafından eklenirse ne olur .. neyse ben benim cümle bir açıklama verdi size karşı gitmek değildir .. Saygılarımızla ...
onalbi


43

Açısal CLI kullananlar için basittir:

src / polyfills.ts

declare global {
  interface Window {
    myCustomFn: () => void;
  }
}

benim-özel-utils.ts

window.myCustomFn = function () {
  ...
};

IntelliJ kullanıyorsanız, yeni çoklu dolgularınız toplanmadan önce IDE'de aşağıdaki ayarı değiştirmeniz gerekir:

> File 
> Settings 
> Languages & Frameworks 
> TypeScript 
> check 'Use TypeScript Service'.

1
declare globalhile ve bu cevap gerçekten açısal CLI için spesifik değil ...
Avindra Goolcharan

31

Bunu çok sık yapmama gerek yok, Redux Devtools'u ara katman yazılımı ile kullanırken oldu.

Ben sadece yaptım:

const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

Veya şunları yapabilirsiniz:

let myWindow = window as any;

ve sonra myWindow.myProp = 'my value';



Bunu yapabilirsiniz, ancak bu sorunun cevabı değil, bir çözümdür
Vitalij

Bu sayede ben kullanarak düzgün typescript altında redux araçları etkinleştirmek olabilir .__ REDUX_DEVTOOLS_EXTENSION__ && (pencere herhangi olarak) (pencere olarak herhangi) .__ REDUX_DEVTOOLS_EXTENSION __ ())
danivicario

20

Diğer cevapların çoğu mükemmel değil.

  • Bazıları sadece dükkan için tür çıkarımını bastırır.
  • Diğerleri sadece global değişkenin isim alanı olduğunu umuyor, arayüz / sınıf olarak değil

Ben de bu sabah benzer bir sorunla karşılaşıyorum. SO üzerinde çok fazla "çözüm" denedim, ancak hiçbiri kesinlikle hiçbir tip hatası üretmiyor ve IDE'de (webstorm veya vscode) tetikleme türünü etkinleştiriyor.

Sonunda, buradan

https://github.com/Microsoft/TypeScript/issues/3180#issuecomment-102523512

, Arabirim / sınıf ve ad alanı olarak hareket eden global değişken için yazımları eklemek için makul bir çözüm buluyorum .

Örnek aşağıdadır:

// typings.d.ts
declare interface Window {
    myNamespace?: MyNamespace & typeof MyNamespace
}

declare interface MyNamespace {
    somemethod?()
}

declare namespace MyNamespace {
    // ...
}

Şimdi, yukarıdaki kod, ad alanının MyNamespaceve arabirimin tiplerini MyNamespaceglobal değişkene myNamespace(pencerenin özelliği) birleştirir.


2
Teşekkürler - bu, ortam dışı modül bağlamında kullanabileceğiniz tek şeydir.
Tyler Sebastian


13

TypeScript Definition Manager kullanıyorsanız, bunu nasıl yapacağınız aşağıda açıklanmıştır !

npm install typings --global

Oluşturun typings/custom/window.d.ts:

interface Window {
  MyNamespace: any;
}

declare var window: Window;

Özel yazınızı yükleyin:

typings install file:typings/custom/window.d.ts --save --global

Bitti, kullan‌ ! Daktilo yazımı artık şikayet etmeyecek:

window.MyNamespace = window.MyNamespace || {};

1
FWIW typings, Typcript 2.0 (2016 ortası) ile eski hale getirildi ve sahibi tarafından arşivlendi.
mrm

13

Typscript, dize özellikleri üzerinde typecheck yapmaz.

window["newProperty"] = customObj;

İdeal olarak, küresel değişken senaryosundan kaçınılmalıdır. Tarayıcı konsolunda bir nesnede hata ayıklamak için bazen kullanıyorum.



8

Typescript 3.x kullanıyorsanız declare global, diğer yanıtlardaki bölümü atlayabilir ve bunun yerine şunları kullanabilirsiniz:

interface Window {
  someValue: string
  another: boolean
}

Typescript 3.3, WebPack ve TSLint kullanırken bu benimle çalıştı.


Çalışmıyor ^3.4.3. Bu cevap benim için çalıştı stackoverflow.com/a/42841166/1114926
Green

7

Referans için (bu doğru cevaptır):

Bir .d.tstanım dosyasının içinde

type MyGlobalFunctionType = (name: string) => void

Tarayıcıda çalışıyorsanız, Window'un arayüzünü yeniden açarak tarayıcının pencere bağlamına üye eklersiniz:

interface Window {
  myGlobalFunction: MyGlobalFunctionType
}

Aynı fikir NodeJS için:

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

Şimdi kök değişkenini (aslında pencerede veya global olarak yaşayacak) beyan edersiniz

declare const myGlobalFunction: MyGlobalFunctionType;

Sonra normal bir .tsdosyada, ancak yan etki olarak içe aktarılırsa, gerçekte uygularsınız:

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

Ve son olarak, kod tabanında başka bir yerde kullanın:

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

myGlobalFunction("Kevin");

Teşekkürler, bu bulduğum en iyi örnek ve iyi çalışıyor.
Nick

6

Özel bir arayüz yapmak Pencereyi genişletir ve isteğe bağlı olarak özel mülkünüzü ekleyin.

Ardından, özel arabirimi kullanan ancak orijinal penceresiyle değerlenen customWindow'a izin verin.

Typescript@3.1.3 ile çalıştı.

interface ICustomWindow extends Window {
  MyNamespace?: any
}

const customWindow:ICustomWindow = window;

customWindow.MyNamespace = customWindow.MyNamespace {} 

5

windowNesne üzerinde hesaplanmış veya dinamik bir özellik ayarlamak isteyenler için , declare globalyöntemle mümkün olmadığını göreceksiniz . Bu kullanım durumunu açıklığa kavuşturmak için

window[DynamicObject.key] // Element implicitly has an 'any' type because type Window has no index signature

Böyle bir şey yapmaya çalışabilirsiniz

declare global {
  interface Window {
    [DyanmicObject.key]: string; // error RIP
  }
}

Yukarıdaki hata olsa. Bunun nedeni, Typcript'te, arabirimlerin hesaplanan özelliklerle iyi oynamaması ve aşağıdaki gibi bir hata atmasıdır.

A computed property name in an interface must directly refer to a built-in symbol

Bunu aşmak windowiçin , döküm önerisiyle <any>gidebilirsiniz.

(window as any)[DynamicObject.key]

3
Bu çok 2019.
Qwerty

4

Create-tepki-uygulama v3.3 kullanarak bunu elde etmenin en kolay yolunu Windowotomatik oluşturulan türü genişletmek olduğunu buldum react-app-env.d.ts:

interface Window {
    MyNamespace: any;
}

3

Öncelikle pencere nesnesini geçerli kapsamda bildirmeniz gerekir.
Çünkü typescript nesnenin türünü bilmek istiyor.
Pencere nesnesi başka bir yerde tanımlandığından, yeniden tanımlayamazsınız.
Ancak şu şekilde beyan edebilirsiniz: -

declare var window: any;

Bu, pencere nesnesini yeniden tanımlamaz veya adıyla başka bir değişken oluşturmaz window.
Bu, pencerenin başka bir yerde tanımlandığı ve yalnızca geçerli kapsamda başvurduğunuz anlamına gelir.

Sonra MyNamespace nesnenize basitçe başvurabilirsiniz: -

window.MyNamespace

Veya windowsadece nesne üzerinde yeni özelliği ayarlayabilirsiniz : -

window.MyNamespace = MyObject

Ve şimdi daktilo şikayet etmeyecek.


nerede windowtanımlandığını bilmek istemeniz durumunda ne yapabilirim ?
Mav55

2

Bunu bugün bir Açısal (6) kütüphanede kullanmak istedim ve beklediğim gibi çalışması biraz zaman aldı.

Kütüphanemin bildirimleri kullanabilmesi için d.ts, global nesnenin yeni özelliklerini bildiren dosyanın uzantısını kullanmak zorunda kaldım .

Sonuçta, dosya şöyle bir şeyle sonuçlandı:

/path-to-angular-workspace/angular-workspace/projects/angular-library/src/globals.d.ts

Bir kez oluşturulduktan sonra, onu açığa çıkarmayı unutmayın public_api.ts.

Bunu benim için yaptı. Bu yardımcı olur umarım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.