TypeScript'te json dosyasını içe aktarma


148

Bir var JSONgörünüyor şu Seviyorum bu dosyayı:

{

  "primaryBright":    "#2DC6FB",
  "primaryMain":      "#05B4F0",
  "primaryDarker":    "#04A1D7",
  "primaryDarkest":   "#048FBE",

  "secondaryBright":  "#4CD2C0",
  "secondaryMain":    "#00BFA5",
  "secondaryDarker":  "#009884",
  "secondaryDarkest": "#007F6E",

  "tertiaryMain":     "#FA555A",
  "tertiaryDarker":   "#F93C42",
  "tertiaryDarkest":  "#F9232A",

  "darkGrey":         "#333333",
  "lightGrey":        "#777777"
}

Onu bir .tsxdosyaya aktarmaya çalışıyorum . Bunun için bunu tür tanımına ekledim:

declare module "*.json" {
  const value: any;
  export default value;
}

Ve bunu böyle ithal ediyorum.

import colors = require('../colors.json')

Ve dosyada rengi primaryMainolarak kullanıyorum colors.primaryMain. Ancak bir hata alıyorum:

'PrimaryMain' özelliği 'typeof "* .json" türünde mevcut değil


3
Modül beyanınız ve ithalat formunuz uyuşmuyor.
Aluan Haddad

2
Bir örnek göstermenin sakıncası var mı? Ben tiptip noob.
Sooraj

Yanıtlar:


94

İçe aktarma formu ve modül beyanı, modülün şekli ve ne ihraç ettiği konusunda anlaşmalıdır.

Yazdığınızda (uyumlu modül formatlarını hedeflerken TypeScript 2.9'dan beri JSON'u içe aktarmak için optimal olmayan bir uygulama nota bakın )

declare module "*.json" {
  const value: any;
  export default value;
}

İle biten bir tanımlayıcıya sahip tüm modüllerin adında.json tek bir dışa aktarım olduğunu belirtiyorsunuz. default .

Böyle bir modülü doğru şekilde tüketmenin birkaç yolu vardır:

import a from "a.json";
a.primaryMain

ve

import * as a from "a.json";
a.default.primaryMain

ve

import {default as a} from "a.json";
a.primaryMain

ve

import a = require("a.json");
a.default.primaryMain

İlk biçim en iyisidir ve kullandığı sözdizimsel şeker, JavaScript'in defaultdışa aktarmasının tam sebebidir .

Ancak size neyin yanlış gittiğine dair bir ipucu vermek için diğer formlardan bahsetmiştim. Sonuncusuna özellikle dikkat edin. requiresize modülün kendisini temsil eden bir nesneyi verir , dışa aktarılan bağlamaları değil .

Öyleyse neden hata? Çünkü sen yazdın

import a = require("a.json");
a.primaryMain

Ve yine adında hiçbir ihracat yoktur primaryMainİSS'niz tarafından beyan "*.json".

Tüm bunlar, modül yükleyicinizin JSON'u defaultorijinal beyanınızda önerildiği gibi dışa aktarım olarak sağladığını varsayar .

Not: TypeScript 2.9'dan bu yana , TypeScript'in içe aktarılan dosyaları analiz etmesini sağlamak ve bir joker modül bildirimi ihtiyacını ortadan kaldıran ve dosyanın varlığını doğrulayan şekilleriyle ilgili doğru bilgiler sağlamak için --resolveJsonModulederleyici bayrağını kullanabilirsiniz .json. Bu, belirli hedef modül formatları için desteklenmez.


1
@Royi bu yükleyicinize bağlıdır. Uzak dosyalar için şunu kullanmayı düşününawait import('remotepath');
Aluan Haddad

28
Aşağıda, daha güncel yanıtları kaydırmaya devam edin.
jbmusso

@jbmusso TypeScript'in sonraki sürümlerinde sunulan iyileştirmelerle ilgili bazı bilgiler ekledim ancak kavramsal olduğu için bu cevabın güncel olmadığını düşünüyorum. Ancak, daha fazla iyileştirme için önerilere açığım.
Aluan Haddad

1
Risk, bazı kişilerin cevabınızın ilk satırlarını kopyalayıp / yapıştırarak, temel nedeni değil yalnızca semptomu düzeltmesidir. @ Kentor'un cevabının daha fazla ayrıntı verdiğine ve daha eksiksiz bir cevap verdiğine inanıyorum. Bir öneri, Notunuzu cevabınızın üzerine taşımak ve bunun bugün itibariyle bu sorunu çözmenin doğru yolu olduğunu açıkça belirtmek olacaktır.
jbmusso

@Atombit açıkça ben dahil birçok insan için çalıştı. Kabul edilen yanıta oy vermeden önce neyin işe yaramadığını açıklamak ister misiniz?
Aluan Haddad

273

TypeScript 2.9. + İle JSON dosyalarını tür güvenliği ve intellisense ile basitçe içe aktarabilirsiniz:

import colorsJson from '../colors.json'; // This import style requires "esModuleInterop", see "side notes"
console.log(colorsJson.primaryBright);

Bu ayarları ( belgeler ) compilerOptionsbölümüne eklediğinizden emin olun :tsconfig.json

"resolveJsonModule": true,
"esModuleInterop": true,

Yan notlar:

  • TypeScript 2.9.0'da bu JSON özelliğinde bir hata var, 2.9.2 ile düzeltildi
  • EsModuleInterop yalnızca coloursJson'un varsayılan içe aktarımı için gereklidir. Eğer bunu false olarak bırakırsanız, o zaman içeri aktarmanız gerekir.import * as colorsJson from '../colors.json'

18
İlle de ihtiyacınız yok esModuleInterop, ama sonra yapmanız gerekiyor import * as foo from './foo.json';- bu esModuleInterop, etkinleştirmeye çalıştığımda benim için başka sorunlara neden oluyordu.
mpen

1
Haklısın, bunu bir yan not olarak eklemeliydim :-).
kentor

10
Not: Ayrıca koymak gerekir böylece Seçenek "resolveJsonModule", "düğüm" modül çözüm stratejisinin olmadan belirlenemez "moduleResolution": "node"SİZİN içine tsconfig.json. Ayrıca, *.jsoniçe aktarmak istediğiniz dosyaların içinde olması gerektiği dezavantajı ile birlikte gelir "rootDir". Kaynak: blogs.msdn.microsoft.com/typescript/2018/05/31/…
Benny Neugebauer

2
@mpen bu doğru, ancak import * as foo from './foo.json'yanlış içe aktarma formu. Kullanılmadığı import foo = require('./foo.json');zaman olmalıesModuleInterop
Aluan Haddad

1
İhtiyacım olan tek "resolveJsonModule": true
Michael Elliott

10

Typcript 2.9+ sürümünü kullanmak kolaydır. Böylece, JSON dosyalarını @kentor tanımlanmış olarak kolayca içe aktarabilirsiniz .

Ancak daha eski sürümleri kullanmanız gerekiyorsa:

JSON dosyalarına daha TypeScript yoluyla erişebilirsiniz. Öncelikle, yeni typings.d.tskonumunuzun dosyanızdaki includemülk ile aynı olduğundan emin olun tsconfig.json.

tsconfig.jsonDosyanızda bir include özelliğiniz yoksa . O zaman klasör yapınız şöyle olmalıdır:

- app.ts
+ node_modules/
- package.json
- tsconfig.json
- typings.d.ts

Ama eğer bir includemülkünüz varsa tsconfig.json:

{
    "compilerOptions": {
    },
    "exclude"        : [
        "node_modules",
        "**/*spec.ts"
    ], "include"        : [
        "src/**/*"
    ]
}

Ardından, mülkiyet bölümünde açıklandığı gibi dizinde typings.d.tsolmalısınızsrcinclude

+ node_modules/
- package.json
- tsconfig.json
- src/
    - app.ts
    - typings.d.ts

Yanıtın çoğunda olduğu gibi, tüm JSON dosyalarınız için genel bir bildirim tanımlayabilirsiniz.

declare module '*.json' {
    const value: any;
    export default value;
}

ama bunun daha yazılı bir versiyonunu tercih ederim. Örneğin, şöyle bir yapılandırma dosyanız config.jsonolduğunu varsayalım:

{
    "address": "127.0.0.1",
    "port"   : 8080
}

O zaman bunun için belirli bir tür bildirebiliriz:

declare module 'config.json' {
    export const address: string;
    export const port: number;
}

Typcript dosyalarınıza içe aktarmak kolaydır:

import * as Config from 'config.json';

export class SomeClass {
    public someMethod: void {
        console.log(Config.address);
        console.log(Config.port);
    }
}

Ancak derleme aşamasında, JSON dosyalarını dist klasörünüze manuel olarak kopyalamanız gerekir. package.jsonYapılandırmama bir komut dosyası özelliği ekledim:

{
    "name"   : "some project",
    "scripts": {
        "build": "rm -rf dist && tsc && cp src/config.json dist/"
    }
}

Rm -rf bir Linux / Unix olayı mı, yoksa bu ol 'Windurz üzerinde de çalışacak mı?
Cody

teşekkürler, benim yazımlarım. d.ts yersizdi. / Src'ye taşındığım anda hata mesajı kayboldu.
Gi1ber7

1
@Cody Bu gerçekten sadece bir Linux / Unix olayı.
Maxie Berkmann

7

TS Tanım dosyanıza, örn. Typings.d.ts`, şu satırı ekleyebilirsiniz:

declare module "*.json" {
const value: any;
export default value;
}

Ardından bunu typecript (.ts) dosyanıza ekleyin: -

import * as data from './colors.json';
const word = (<any>data).name;

2
Bu çok kötü bir fikir.
Aluan Haddad

3
lütfen neden kötü olduğunu açıklar mısınız ??? Daktilo konusunda uzman değilim. @AluanHaddad
Mehadi Hassan

5
Tip iddianız anyiki şey söylüyor. 1) basitçe tanımı gereği ön yüzünde yanlış beyan veya içe aktardığınız. Sizin gerektiğini asla her koşulda kendinizi ilan ettik bir modülün bir ithalat türüdür iddiayı yerleştirmek gerekmez. 2) bunu çalışma zamanında bir şekilde çözen çılgın bir yükleyiciniz olsa bile, tanrılar korusun, yine de verilen şekle sahip bir modüle erişmenin delice kafa karıştırıcı ve en kırılgan yolu olacaktır. * as x fromve x fromOP'de olandan daha fazla uyumsuz çalışma zamanı bilgisine sahiptir. Cidden bunu yapma.
Aluan Haddad

5
Cevabınız için teşekkürler. Açıkça anladım. @AluanHaddad
Mehadi Hassan

2

Gitmenin başka bir yolu

const data: {[key: string]: any} = require('./data.json');

Bu, istediğiniz json türünü hala tanımlayabiliyordunuz ve joker karakter kullanmak zorunda değilsiniz.

Örneğin, özel tür json.

interface User {
  firstName: string;
  lastName: string;
  birthday: Date;
}
const user: User = require('./user.json');

2
Bunun soruyla hiçbir ilgisi yoktur ve aynı zamanda kötü bir uygulamadır.
Aluan Haddad

0

Genellikle Node.js uygulamalarında bir .json gereklidir. TypeScript 2.9 ile --resolveJsonModule, .json dosyalarından türlerin içe aktarılmasına, çıkarılmasına ve oluşturulmasına izin verir.

Misal #

// tsconfig.json

{
    "compilerOptions": {
        "module": "commonjs",
        "resolveJsonModule": true,
        "esModuleInterop": true
    }
}

// .ts

import settings from "./settings.json";

settings.debug === true;  // OK
settings.dry === 2;  // Error: Operator '===' cannot be applied boolean and number


// settings.json

{
    "repo": "TypeScript",
    "dry": false,
    "debug": false
}
tarafından: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html

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.