TypeScript. Cum să folosești definițiile de tip neexportate?


Uită-te doar la acest cod TypeScript:

lib.ts

interface Human {
    name: string;
    age: number;
}

export default class HumanFactory {
    getHuman(): Human {
        return {
            name: "John",
            age: 22,
        }
    }
}

index.ts

import HumanFactory from "./lib";

export class Foo {
    human: any;

    constructor() {
        const factory = new HumanFactory();
        this.human = factory.getHuman();
    }

    diffWithError(age: number): number {
        return age - this.human.name;
    }

    diffWithTypingAndAutocoplete(age: number): number {
        const factory = new HumanFactory();
        return age - factory.getHuman().name;
    }
}

Problema este în proprietatea „human” a clasei „Foo”. Nu pot defini tipul acestei variabile ca interfață „Human” din lib.ts.

În metoda „diffWithError” fac o eroare - folosesc numărul „age” și șirul „name” într-o operație aritmetică, dar nici IDE-ul, nici compilatorul ts nu știu despre asta, pentru că în acest context, tipul lui „this.human.name” este „any”

În metoda „diffWithTypingAndAutocoplete” folosesc doar metoda „getHuman”. IDE-ul și compilatorul știu despre tipul rezultatului metodei. Aceasta este interfața „Human” și câmpul „name” este de tip „string”. Această metodă declanșează o eroare la compilarea surselor.

Am întâlnit această problemă atunci când am încercat să import un fișier .d.ts al unei biblioteci JS și nu am posibilitatea de a exporta interfața necesară. Pot cumva să definesc un tip valid pentru proprietatea "human" fără să copiez și să lipesc codul interfeței "Human" de fiecare dată când vreau să definesc tipul (și fără definiții de tip inline, cum ar fi { name: string, age: number })?

Nu vreau să creez instanțe ale claselor neexportate, vreau doar verificarea tipurilor și completarea automată.

P.S. Încerc să scriu asta:

human: Human

compilatorul declanșează o eroare: "eroare TS2304: Nu se poate găsi numele 'Human'" (comportament așteptat)

P.S.S. Încerc să fac asta cu directiva cu triple slash:

///<reference path="./lib.ts" />

dar nici asta nu funcționează.

Îmi pare rău pentru engleza mea slabă și mulțumesc pentru răspunsuri

Răspuns #1

Actualizare

Acum, cu tipuri condiționale implementate, se poate face fără soluții alternative:

type Human = ReturnType<HumanFactory['getHuman']>

Ocolire pentru TS < 2.8

Dacă nu poți schimba lib.ts, poți „interoga” tipul de întoarcere al funcției getHuman. Este puțin dificil pentru că TypeScript în prezent nu oferă nicio metodă directă pentru aceasta:

import HumanFactory from "./lib";

const dummyHuman = !true && new HumanFactory().getHuman();
type Human = typeof dummyHuman;

export class Foo {
  human: Human;

  // ...
}

!true && este folosit pentru a preveni executarea new HumanFactory().getHuman().

Răspunsul #2

Am găsit o soluție!

Creez fișierul human-interface.ts cu acest conținut:

import HumanFactory from './lib';

const humanObject = new HumanFactory().getHuman();
type HumanType = typeof humanObject;

export default interface Human extends HumanType {}

Importul acestei interfețe în fișierul principal nu execută crearea „HumanFactory” și verificarea tipului funcționează corect.

Mulțumesc pentru ideea cu typeof