interface Person {name: string;}
x9.is<Person>({ name: 'Bob' }); // true
x9.is<Person>(7); // false

It works with generics too

interface Boxed<T> {  value: T;}x9.is<Boxed<string>>({ value: 'lala' }); // true

It can also be used as a type guard:

if (x9.is<Person>(bob)) {  console.log(bob.name);}

Limitations

Functions

At runtime, function values don’t carry any information. They are just functions. This means that the best we can do is tell you if somethig is or isn’t a function.

// works as expected
x9.is<() => any>(() => {}); // true

// the following should be false,
// since the return types don't match
// but this information won't be available at runtime

x.is<() => string>(() => 5); // true
// the following should be false
// since the parameters don't match
// but it will still be true
x9.is<(x: string) => any>(() => {}); // true

The compiler will emit a warning if it determines you’re checking for functions.

Note: The number of arguments for a function is also available at runtime (via function.length). However, this information is unreliable(ex: code could go through transformations that use rest parameters or rely on the arguments object, etc). For this reason, we prefer to discard it altogether.

Classes and instanceof?

Note: We need feedback here.

For example:

// when you declare a classclass Person {  constructor(public readonly name: string) {}}// TypeScript automatically generates the following interfaceinterface Person {  readonly name: string;}

So when you reference the Person identifier, you can be referencing either the class “value” (the constructor function) or the class “type” (the interface)