488 votes

Primordial de l'interface de la propriété type défini dans la Machine d.fichier ts

Est-il un moyen de changer le type d'une interface bien définie dans un *.d.ts dans le tapuscrit?

par exemple: Une interface en x.d.ts est défini comme

interface A {
  property: number;
}

Je veux le changer dans le fichier d'enregistrement des fichiers que je vous écris pour

interface A {
  property: Object;
}

ou même ce serait le travail

interface B extends A {
  property: Object;
}

Cette approche de travail? Il ne fonctionne pas quand je l'ai essayé sur mon système. Voulez juste pour confirmer si c'est encore possible?

929voto

ZSkycat Points 211

J'utilise une méthode que les premiers filtres les champs, puis les combine.

référence Exclut les biens de 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
}

298voto

Qwerty Points 1165

Inspiré par ZSkycat de l' extends Omit solution, je suis arrivé à ceci:

type Modify<T, R> = Pick<T, Exclude<keyof T, keyof R>> & R

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

type B = Modify<A, {
  a: number;
  b: number;
}>
// { a: number; b: number; c: number; }

Va étape par étape:

type T0 = Exclude<keyof A, 'a'> // "b" | "c"
type T1 = Pick<A, T0>           // { b: boolean; c: number; }
type T2 = T1 & {a: number}      // { a: number; b: boolean; c: number; }

77voto

Nitzan Tomer Points 11798

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

Vous pouvez ajouter une propriété:

interface A {
    newProperty: any;
}

Mais le changement d'un type de existant:

interface A {
    property: any;
}

Conduit à une erreur:

Ultérieure des déclarations de variables doivent avoir le même type. Variable "propriété" doit être de type "nombre", mais ici est de type 'tout'

Bien sûr, vous pouvez avoir votre propre interface qui s'étend d'un existant. Dans ce cas, vous pouvez remplacer un type uniquement à un type compatible, par exemple:

interface A {
    x: string | number;
}

interface B extends A {
    x: number;
}

Par le chemin, vous devriez probablement éviter d'utiliser des Object comme un type, au lieu d'utiliser le type any.

Dans les docs pour l' any type , il est indiqué:

Le tout est un moyen puissant pour travailler avec du code JavaScript, vous permettant progressivement de l'opt-in et opt-out de la vérification de type cours la compilation. Vous pourriez vous attendre Objet à jouer un rôle similaire, comme il dans d'autres langues. Mais les variables de type Objet ne vous permettent pour attribuer une valeur quelconque d'entre eux vous ne pouvez pas appeler les méthodes arbitraires sur eux, même ceux qui existent réellement:

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'.

44voto

ryanjduffy Points 2441

L'extension @zSkycat réponse un peu, vous pouvez créer un générique qui accepte les deux types d'objet et renvoie une fusion de type avec les membres de la deuxième substituant les membres de la première.

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;

3voto

Egor Malkevich Points 989

C'est drôle j'ai passer la journée à enquêter sur la possibilité de résoudre le même cas. J'ai trouvé qu'il 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;
}

Provoquer Un module ne peuvent pas connaître tous les types disponibles dans votre application. Et c'est assez ennuyeux port de tout, de partout et de faire un code comme ceci.

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

Vous devez définir le type plus tard la saisie semi-automatique fonctionne bien.


De sorte que vous pouvez tricher un peu:

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

Gauche certains type par défaut, qui permettent la saisie semi-automatique, où les remplace pas nécessaire.

Alors

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

type SomeOtherType = {
  coolStuff: number
}

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

Désactiver stupide exception ici à l'aide de @ts-ignore drapeau, en disant: nous le faisons-nous quelque chose de mal. Et drôle de chose que tout fonctionne comme prévu.

Dans mon cas, je suis réduisant le champ de vision de type x, sa me permet de faire du code plus suspectés. Par exemple, vous avez liste de 100 propriétés, et vous réduire à 10, afin d'éviter des situations stupides

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X