typescript - Odota 'Type' kolmannen osapuolen kirjastofunktioilta


Olen hyvin uusi TypeScriptin kanssa. Minulla on tilanne, jossa haluan määrittää tyypin muuttujalle, jonka arvo palautetaan kolmannen osapuolen kirjaston funktiosta ja jolla on oma tyyppimääritelmänsä.

Esimerkiksi:

import {omit} from 'lodash'

interface ITest {
  a: String;
}

const foo: Object = {
  a: "dfdf",
  b: "sdfsdf",
}

const expected: ITest = omit(foo, 'b')

Tämä näyttää tämän virheen

[ts] Tyyppi '{}' ei ole määriteltävissä tyypiksi 'ITest'.

Ominaisuus 'a' puuttuu tyypistä '{}'.

Teenkö sen väärin vai eikö se ole mahdollista?

Vastaus #1

Tämä tapahtuu, koska omitilla on hyvin vähän rajoituksia palautetyypilleen, ja se palauttaa oletuksena {}. Tutustu omit-määritelmiin, jos haluat perehtyä tähän:

interface LoDashStatic {
    omit<TResult extends {}, T extends {}>(
        object: T,
        ...predicate: (StringRepresentable|StringRepresentable[])[]
    ): TResult;
}

Tämä sanoo, että omitilla on kaksi geneeristä parametria (TResult ja T, jotka molemmat ovat vähintään {}). Sillä on myös yksi pakollinen parametri (object) ja 0 tai useampi predicate (merkkijonoja, enemmän tai vähemmän). Geneerinen parametri T on sen syötteen tyyppi, ja TResult on funktion kokonaispalautustyyppi.

Kun et määritä geneerisiä parametreja, TypeScript päättelee ne. Nämä parametrit eivät kuitenkaan liity toisiinsa, tai juuri mihinkään muuhun, joten niiden tarkka päättely on vaikeaa. Se voi päätellä T:n: se on parametrin tyyppi, joka sille annetaan. TResult:n osalta sillä ei kuitenkaan ole mitään tietoa. Jos kutsut funktiota ja käytät arvoa heti, joissakin tapauksissa se riittää päättämään, mitä funktion oletetaan palauttavan (eli mikä TResult on), mutta sinun tapauksessasi se ei riitä, joten se päädytään päättelemään {}.

Kun olet itse asiassa kutsunut omit-funktiota koodissasi, yrität sitten antaa tuon {} ITest-tyypille, mikä ei ole varmasti turvallista - on mahdollista saada tyhjä objekti, jolla ei ole a-ominaisuutta, eikä tämä olisi oikein.

Sinulla on kaksi vaihtoehtoa ratkaista tämä:

  • Käytä tyyppivarmennusta: const expected=<ITest> omit(foo, 'b')

    Tässä kerrot kääntäjälle, että olet varma, että tämä on ITest. Se sallii sen (ja antaa expected-muuttujalle ITest-tyypin), niin kauan kuin on mahdollista, että olet oikeassa - sinun ei tarvitse olla täysin oikeassa, kuten tavallisen määrityksen kanssa.

  • Määritä funktion palautustyyppi antamalla geneeriset parametrit, joita omit käyttää eksplisiittisesti: const expected=omit<ITest, {}>(foo, 'b').

    Tällä hetkellä näitä parametreja päätellään automaattisesti, mutta näillä tyyppimäärittelyillä ei ole mitään tapaa johtaa 'oikeaa' tyyppiä ("foo:n tyyppi, mutta ilman 'a':ta"), joten päädyt mahdollisimman yleiseen palautustyyppiin: {}. Jos asetat nämä generiikat nimenomaisesti, voit hallita tätä tarkemmin. Haluat todellisuudessa määrittää vain yhden generiikkaparametrin tässä (palautustyypin), mutta sitä ei valitettavasti voi tehdä: sinun täytyy määrittää joko molemmat tai kumpikaan.

Henkilökohtaisesti käyttäisin tyyppivarmistusta, mutta mielestäni tästä eteenpäin kyse on henkilökohtaisesta mausta.