型が到達できないときの型超大国の維持


それはあまりにも一般的です.あなたは、外部ライブラリを利用して、タイプスクリプトで離れてコーディングしているし、あなたが見つけることができないタイプのコードを回避している!あなたが探していたタイプはエクスポートされていません!
ローカルのタイプを再作成したり、リポジトリをフォークしたり、タイプをエクスポートしたり、持っているものを使ったりすることもできます.今日、私は後者をする方法をあなたに示すつもりです.

推論型の戻り値


次のように明示的に定義された型情報を持たないオブジェクトを返す外部ライブラリから関数を利用しているとしましょう.
const divideNumber = (dividend: number, divisor: number) => {
  const quotient = dividend / divisor;
  return { dividend, divisor, quotient };
};

/**
 * This function serves as an example of a function which returns
 * an inferred type, meaning the return type is not explicitly
 * defined by the developer.
 */
この関数を使用する場合、TypeScriptは次のように自動的に型を推論します.
{
     dividend: number;
     divisor: number;
     quotient: number;
}

/**
 * This is what the inferred return type of the previous function 
 * looks like.
 */
これは基本的な使い方には適していますが、タイプで何かをしたい場合は難しくなります.
あなたが不慣れであるならばReturnType , あなたの最初の本能は次のように自分をタイプすることであるかもしれません、しかし、そうすることは我々が真実の一つの源から逸脱していることを意味します.
interface DivisionObject {
  dividend: number;
  divisor: number;
  quotient: number;
}

/**
 * This is a bad example of a solution to define a type for the
 * return type of the previous function.
 */
ありがとうReturnType , 関数型シグネチャであるジェネリックは、明示的に名前を付けられなくても、その戻り値の型を返します.
私たちは直接それを使用するか、またはそれ自身の名前付きの型にそれを割り当てることができます.
import { divideNumber } from "@fake-library/math";

type DivisionObject = ReturnType<typeof divideNumber>;

/**
 * Here we are using the ReturnType generic to define a type as
 * the inferred return type of the divideNumber function.
 */
これを別のローカル関数のプロパティとして使うことができます.
const verifyDivision = ({ dividend, divisor, quotient }: DivisionObject) => {
  return divisor * dividend === quotient;
};

/**
 * Here we're taking the type we defined and defining it as the
 * first property of the verifyDivision function.
 */
🎉 すごい!これはとても良いです!

ネストされた、名前のない型


時々、エクスポートされた型を持っていますが、その型の1つのプロパティが欲しいだけです.もう一度、あなたがtypescriptに慣れていないならば、あなたの最初の本能は単にタイプを再宣言するかもしれません.しかし、我々は実際に我々の便利な角括弧を使用して、それにアクセスすることができます.
次のインターフェイスがあるとしましょう.
interface HumanBeing {
  firstName: string;
  lastName: string;
  locale: {
    country: string;
    language: "english" | "french" | "spanish";
    timeZone: string;
  };
}
さて、人間の言語が英語であるかどうかをチェックする関数を作りたいとしましょう.
type HumanBeingLanguage = HumanBeing["locale"]["language"];

const isLanguageEnglish = (language: HumanBeingLanguage) => {
  return language === "english";
};
✨ 簡単なpeasy、右?

変数名のないオブジェクト型シグネチャ


これはもう少しあいまいですが、私はカスタムの概念レンダラを作成中に何かをlatest version of my personal portfolio . オブジェクトの複数のタイプのシグネチャを持っている配列を持っていて、可能なオブジェクト型が名前を付けられていない場合、物事は非常に速くyuckyを得ることができます.
type CustomHTMLElement =
  | {
      tag: "img";
      attributes: {
        src: string;
        alt: string;
      };
    }
  | {
      tag: "video";
      attributes: {
        src: string;
        type: string;
      };
    };

/**
 * As you can see, the above type can have multiple different
 * object type signatures, despite being under the same namespace.
 */
ご覧の通り、属性は一貫性がありません.
私たちを利用するオブジェクトの配列を定義しましょうCustomHTMLElement 種類
const customElements: CustomHTMLElement[] = [
  {
    tag: "img",
    attributes: {
      src: "https://example.com/image.png",
      alt: "Example image",
    },
  },
  {
    tag: "video",
    attributes: {
      src: "https://example.com/video.mp4",
      type: "video/mp4",
    },
  },
];
すべてのリストを取得したいとしましょうimg 要素は、私たちの最初の本能は、生を使用することがありますArray#filter メソッド.
const getAllImgElements = () => {
  return customElements.filter(({ tag }) => tag === "img");
};

getAllImgElements().forEach((element) => {
  element.attributes.alt; /** Property 'alt' does not exist on type
                            '{ src: string; alt: string; }
                           | { src: string; type: string; }'.
                                                    */
});

/**
 * Unfortunately, using filter with this type, we get an 
 * error since TypeScript cannot make an inference from this
 * method.
 */
ご覧の通り、この問題はArray#filter すぐに型推論を尊重しません.Typescriptには、他のオブジェクト型のいずれかが可能性として削除されたという考えはまだありません.
この場合、getAllImgElements 機能は() => CustomHTMLElement[] , それで、我々はまだあいまいさの正確な同じ元の程度を持ちます.
ありがたいことに、我々はExtract TypeScript 2.8 +で利用可能なジェネリックタイプは、typescript述語と組み合わせました.
type CustomHTMLElementTag<T> = Extract<CustomHTMLElement, { tag: T }>;

const getAllImgElements = () => {
  return customElements.filter(
    (element): element is CustomHTMLElementTag<"img"> => element.tag === "img"
  );
};

getAllImgElements().forEach((element) => {
  element.attributes.alt; /** TypeScript is happy! 🎉 */
});

/**
 * Here, we're using a type guard, a type predicate, and the
 * TypeScript Extract generic to tell TypeScript which type
 * is making it out the other end. 
 */

結論


TypeScriptは絶対の獣です、しかし、そのサブセット言語の性質のために:JavaScript、ものは時々少しファンキーになることができます.幸いにも、我々はすべての課題が大好きです.
あなたは私のこのようなコンテンツを読むことができますpersonal blog!
あなたがこの投稿が好きなら、将来の投稿で最新の状態に保つために私をチェックアウト!❤️