1
votes

Pouvons-nous utiliser des symboles globaux dans les fichiers de déclaration Typescript?

J'essaie d'implémenter quelque chose comme ça, mais je ne suis pas sûr que ce soit possible. Je pense que Typescript n'autorise que des symboles uniques, pas des symboles globaux. Est-ce correct?

Y a-t-il un meilleur moyen de parvenir à utiliser des symboles globaux?

// sample.d.ts
const mySymbol = Symbol.for('internal.symbol')

interface Sample{
    [mySymbol]: string
    a: number
    b: number
}

// sample.js
class SampleClass implements Sample {
    [mySymbol]: string
    a: number
    b: number

    constructor(a: number, b: number){
        this.a = a;
        this.b = b;
        this[mySymbol] = `${a}-${b}`
    }
}

let mySample = new SampleClass(1, 2)

Y a-t-il un moyen d'accomplir cela? mySymbol peut (et sera idéalement) un symbole global qui sera également utilisé par d'autres objets afin qu'il puisse être défini séparément si cela est possible.


0 commentaires

3 Réponses :


0
votes

Vous pouvez exporter votre symbole, c'est-à-dire

export const mySymbol = Symbol.for('internal.symbol')

, puis l'importer dans le fichier qui en a besoin. De cette façon, vous ne polluerez pas la portée globale et vous ne pourrez l'importer que si nécessaire.


5 commentaires

J'espérais faire cela à partir d'un fichier .d.ts comme le type ou l'interface. Mais il semble qu'il doive être exporté à partir d'un fichier .ts normal, puis importé dans le .d.ts? Est-ce correct?


Les fichiers @tagyoureit d.ts sont le produit de la compilation de vos fichiers TypeScript, vous ne devriez pas les utiliser directement pendant le développement.


Les fichiers .d.ts sont des fichiers de déclaration et assez standard dans TypeScript ( typescriptlang. org / docs / handbook / declaration-files /… )


Oui, ils sont standard, mais en pratique, lorsque vous utilisez un bundler tel que webpack, vous n'avez pas besoin d'utiliser directement les fichiers d.ts. Voir ici également. Je suppose que si vous n'utilisez pas de bundler, je peux voir pourquoi vous posez la question.


Correct, je n'utilise pas Webpack et n'utilise pas les fichiers de déclaration pour la cohérence entre les différentes parties de mon application. Mais votre réponse m'a aidé à trouver quelque chose qui fonctionne. Je posterai ça ci-dessous. Merci.



1
votes

Voici comment j'ai pu y parvenir.

// misc.ts
export const mySymbol = Symbol.for('internal.symbol')

// sample.d.ts
import {mySymbol} from './misc'

export as namespace Sample
export = Sample
interface Sample{
    [mySymbol]: string
    a: number
    b: number
}

// sample.js
class SampleClass implements Sample {
    [mySymbol]: string
    a: number
    b: number

    constructor(a: number, b: number){
        this.a = a;
        this.b = b;
        this[mySymbol] = `${a}-${b}`
    }
}

let mySample = new SampleClass(1, 2)

Une fois que mySymbol est importé dans le fichier de déclaration, il se transforme en module. Par conséquent, il doit être spécifiquement exporté avec export = Sample et export as namespace Sample . Voir exemple de module.d.ts a >.


2 commentaires

C'est donc ce que j'ai dit dans ma réponse. Exportez le symbole, puis importez-le dans le fichier qui en a besoin.


Oui et merci. J'avais encore un peu de mal avec l'implémentation (les exemples de code seraient encore meilleurs la prochaine fois), alors je l'ai documenté ici pour que quiconque puisse le recréer facilement.



0
votes

... Je pense que Typescript n'autorise que des symboles uniques, pas des symboles globaux. Est-ce correct?

Tous les symboles sont uniques. C'est invariant.

Comment définir la portée et accéder aux symboles est une autre question.

Il existe deux façons de créer des symboles:

Première manière strong>: Symbole (mnémonique?: chaîne) , par exemple

Symbol.for(globalKey:string):symbol{
  if (globalSymbolMap.has(globalKey)
    return globalSymbolMap.get(globalKey)
  else{
    const s=Symbol(globalKey)
    globalSymbolMap.set(globalKey,s)
    return s
  }
}

Chaque appel à Symbol (...) crée un symbole unique. Le mnémonique n'est qu'une propriété pratique pour le débogage, etc. Deux symboles peuvent avoir le même mnémonique sans être le même symbole.

import {x} from './x'
import {y} from './y'
assert(x===y) // pass
const z = Symbol.for('my.global.symbols.1')
assert(x===z) // pass

Lorsque les symboles sont créés de cette manière, ils n'existent que tant qu'ils sont référencés dans le code utilisateur - tout comme autres objets, ils peuvent être récupérés.

Deuxième méthode : Symbol.for (globalKey: string) , par exemple

Dans le fichier 'x.js', sans aucune instruction import / nécessite

const x = Symbol.for('my.global.symbols.1')
export y

Dans le fichier 'y. js ', sans aucune instruction import / ne nécessitant

const x = Symbol.for('my.global.symbols.1')
export x

Dans le fichier' z.js ' p >

console.log(x.toString()) // 'Symbol(optional name)'
assert(x.toString()===y.toString()) // pass
assert(x!==y) // pass

Dans ce cas, un symbole global unique est créé pour chaque clé globale UNIQUE passée comme paramètre globalKey à Symbol.for (globalKey: string ) - à partir de n'importe quel fichier. L'instance de symbole est stockée dans un espace global opaque, comme s'il y avait une carte globale opaque:

const x = Symbol('optional name')
const y = Symbol('optional name')
assert(x!==y) // pass

(bien que ce ne soit peut-être pas ainsi qu'il est réellement implémenté). P >

Voici ce que MDN dit à propos Symbol.for () :

Contrairement à Symbol (), la fonction Symbol.for () crée un symbole disponible dans une liste de registre de symboles globale. Symbol.for () ne crée pas nécessairement un nouveau symbole à chaque appel, mais vérifie d'abord si un symbole avec la clé donnée est déjà présent dans le registre. Dans ce cas, ce symbole est renvoyé. Si aucun symbole avec la clé donnée n'est trouvé, Symbol.for () créera un nouveau symbole global.

À propos de la récupération de place pour ces symboles gérés globalement - je ne sais pas lequel des énoncés suivants est vrai:

  • Lorsqu'un symbole géré globalement n'est plus référencé par un code utilisateur (c'est-à-dire sans inclure la référence de la carte «virtuelle» globale opaque), il peut être récupéré.

  • / p>

Du point de vue de la «logique» du code utilisateur, il n'y aurait aucune différence entre les deux - c'est entièrement un problème d'implémentation. Cependant, les performances, y compris l'utilisation de la mémoire, seraient différentes. Je suppose que certains garbage collection sont activés.


0 commentaires