title: Cross-interface type guards
body: <p>Say a <code>schema</code> object validates a <code>data</code> object.</p>
  <p>Is there any kind of dark magic that would allow us to narrow down the type of a <code>data</code> property after a <code>schema</code>-based type guard?</p>
  <p>Snippets are worth a thousand words:</p>
  <pre class="lang-js prettyprint-override"><code>function validate(data: Data, schema: Schema) {}
  
  interface Data {
    [key: string]: number | string | undefined;
  }
  
  interface Schema {
    properties: {
      [key: string]: { type: &quot;number&quot; | &quot;string&quot; } | undefined;
    };
  }
  
  // Just for demo purposes: we don't know its exact shape until run time.
  const schema: Schema = {
    properties: {
      firstName: {
        type: &quot;string&quot;,
      },
    },
  };
  
  // Idem.
  const data: Data = {
    firstName: &quot;John&quot;,
  };
  
  validate(data, schema); // What kind of magic could happen here...
  
  if (schema.properties.firstName?.type === &quot;string&quot;) {
    const firstName: string = data.firstName; // ...so that there's no error here?
  }
  </code></pre>
  <p><a href="https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABANwIYBsYBNVQKYAUOUqAXIgCK6oA0iAzhABZ4C2ZiAys26gJSIA3gF8AsACgJMMPgBOwVBDyVqQiYkQBtANZ4AnuXpRZ0gOYBdcmBCsARnlmIAPg2NnnicFjzBpeLADcEmKS4tJyCkpcPOxq4hoADrJwCQ6wePTkguoaWroGriZgFlmIUHqp5ABE1nYOVR5VRkWmDcIeXj5+gTnCQeIhEgD0Q4gAUiBGiMBwjt6scIgJILIJcPQZ5ADuylgIAORQiNpgcFuIMFD0iHgAHopH9EyoqZ4yMOiIsuBlMKx4ADoJBAEFNGCx2ORuBDUIgALxxRLJVKydKZRG5XyyIwAOVQ-yyOVyZQqeGqzTMVRoRMQwmp8Vp9L6EmGowAkvMgeIQWApsQOFQSPCMVjcfiyYgqmM4EwwFTgv0JGhMMRCPy6ODeHwAogRogAOrPI7aaRYRBwYCIdimGAQRAgkDoM3PBKpJAsWSAgFcqSWgia9gApIpNIwDIA0VQPH-AD8APKrzhSclFOKVQE2QZPKmkejEtTpmF-IjMGxUfFOr13oB9EWUCNZQ9eH211ON1kyUcTZjwSAA" rel="nofollow noreferrer">Playground</a></p>
  <p>I'm thinking about turning <code>Schema</code> into a class with a custom getter function that would rely on the <code>asserts</code> keyword to type the <code>data</code> property accordingly. (1) I'm not sure it's feasible and (2) there may be a better way.</p>
  <p>Any idea?</p>