web-dev-qa-db-fra.com

Remplacement du type de propriété d'interface défini dans le fichier TypeScript d.ts

Existe-t-il un moyen de modifier le type de propriété d'interface défini dans un *.d.ts in dactylographié?

par exemple: une interface dans x.d.ts est définie comme

interface A {
  property: number;
}

Je veux le changer dans les fichiers TypeScript que j'écris

interface A {
  property: Object;
}

ou même cela fonctionnerait

interface B extends A {
  property: Object;
}

Cette approche fonctionnera-t-elle? Cela n'a pas fonctionné lorsque j'ai essayé mon système. Je veux juste confirmer si c'est même possible?

48
Abdul23

Vous ne pouvez pas changer le type d'une propriété existante.

Vous pouvez ajouter une propriété:

interface A {
    newProperty: any;
}

Mais changer un type d'existant:

interface A {
    property: any;
}

Résultats en erreur:

Les déclarations de variables suivantes doivent avoir le même type. La variable 'propriété' doit être de type 'numéro', mais ici, le type 'tout'

Vous pouvez bien sûr avoir votre propre interface qui étend une interface existante. Dans ce cas, vous pouvez remplacer un type uniquement par un type compatible, par exemple:

interface A {
    x: string | number;
}

interface B extends A {
    x: number;
}

En passant, vous devriez probablement éviter d'utiliser Object comme type, utilisez plutôt le type any.

Dans le docs pour le type any , il est indiqué:

Any est un moyen puissant de travailler avec le code JavaScript existant, vous permettant d’activer et de désactiver progressivement la vérification de type lors de la compilation. Vous pouvez vous attendre à ce que Object joue un rôle similaire, comme dans d'autres langues. Mais les variables de type Object ne permettent que de leur attribuer une valeur. Vous ne pouvez pas y appeler de méthodes arbitraires, même celles qui existent :

let notSure: any = 4;
notSure.ifItExists(); // okay, ifItExists might exist at runtime
notSure.toFixed(); // okay, toFixed exists (but the compiler doesn't check)

let prettySure: Object = 4;
prettySure.toFixed(); // Error: Property 'toFixed' doesn't exist on type 'Object'.
25
Nitzan Tomer

J'utilise une méthode qui filtre d'abord les champs, puis les combine.

référence propriété d'exclusion du type

interface A {
    x: string
}

export type B = Omit<A, 'x'> & { x: number };

pour l'interface:

interface A {
    x: string
}

interface B extends Omit<A, 'x'> {
  x: number
}
49
ZSkycat
type ModifiedType = Modify<OriginalType, {
  a: number;
  b: number;
}>

Inspiré par la solution de ZSkycatextends Omit, j'ai proposé ceci:

type Modify<T, R> = Omit<T, keyof R> & R;

// before [email protected]
type Modify<T, R> = Pick<T, Exclude<keyof T, keyof R>> & R

Exemple:

interface OriginalType {
  a: string;
  b: boolean;
  c: number;
}

type ModifiedType  = Modify<OriginalType , {
  a: number;
  b: number;
}>

// ModifiedType = { a: number; b: number; c: number; }

Aller étape par étape:

type T0 = Exclude<'a' | 'b' | 'c' , 'a' | 'b'> // 'c'
type T1 = Pick<OriginalType, T0>               // { c: number; }
type T2 = T1 & {a: number, b: number }         // { a: number; b: boolean; c: number; }
24
Qwerty

En étendant un peu la réponse de @ zSkycat, vous pouvez créer un générique qui accepte deux types d’objet et renvoie un type fusionné avec les membres du second remplaçant les membres du premier.

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
type Merge<M, N> = Omit<M, Extract<keyof M, keyof N>> & N;

interface A {
    name: string;
    color?: string;
}

// redefine name to be string | number
type B = Merge<A, {
    name: string | number;
    favorite?: boolean;
}>;

let one: A = {
    name: 'asdf',
    color: 'blue'
};

// A can become B because the types are all compatible
let two: B = one;

let three: B = {
    name: 1
};

three.name = 'Bee';
three.favorite = true;
three.color = 'green';

// B cannot become A because the type of name (string | number) isn't compatible
// with A even though the value is a string
// Error: Type {...} is not assignable to type A
let four: A = three;
21
ryanjduffy

C'est drôle, je passe la journée à étudier la possibilité de résoudre le même cas. J'ai trouvé que ce n'est pas possible de faire de cette façon:

// a.ts - module
export interface A {
    x: string | any;
}

// b.ts - module
import {A} from './a';

type SomeOtherType = {
  coolStuff: number
}

interface B extends A {
    x: SomeOtherType;
}

Cause Un module peut ne pas connaître tous les types disponibles dans votre application. Et c'est assez ennuyeux de tout porter de partout et de faire un code comme celui-ci.

export interface A {
    x: A | B | C | D ... Million Types Later
}

Vous devez définir le type plus tard pour que la complétion automatique fonctionne bien.


Donc, vous pouvez tricher un peu:

// a.ts - module
export interface A {
    x: string;
}

A laissé le type par défaut, qui autorise les travaux de saisie semi-automatique, lorsque les remplacements ne sont pas obligatoires.

Ensuite

// b.ts - module
import {A} from './a';

type SomeOtherType = {
  coolStuff: number
}

// @ts-ignore
interface B extends A {
    x: SomeOtherType;
}

Désactivez l'exception stupide ici en utilisant @ts-ignore flag, en nous disant que nous faisons quelque chose de mal. Et drôle, tout fonctionne comme prévu.

Dans mon cas, je réduis la vision du type x, cela me permet de faire du code plus strict. Par exemple, vous avez une liste de 100 propriétés et vous la réduisez à 10 pour éviter les situations stupides

3
Egor Malkevich