You can achieve what you want without the instanceof keyword as you can write custom type guards now:
interface A {
member: string;
}
function instanceOfA(object: any): object is A {
return 'member' in object;
}
var a: any = {member: "foobar"};
if (instanceOfA(a)) {
alert(a.member);
}
Lots of Members
If you need to check a lot of members to determine whether an object matches your type, you could instead add a discriminator. The below is the most basic example, and requires you to manage your own discriminators... you'd need to get deeper into the patterns to ensure you avoid duplicate discriminators.
interface A {
discriminator: 'I-AM-A';
member: string;
}
function instanceOfA(object: any): object is A {
return object.discriminator === 'I-AM-A';
}
var a: any = {discriminator: 'I-AM-A', member: "foobar"};
if (instanceOfA(a)) {
alert(a.member);
}
Answer from Fenton on Stack OverflowYou can achieve what you want without the instanceof keyword as you can write custom type guards now:
interface A {
member: string;
}
function instanceOfA(object: any): object is A {
return 'member' in object;
}
var a: any = {member: "foobar"};
if (instanceOfA(a)) {
alert(a.member);
}
Lots of Members
If you need to check a lot of members to determine whether an object matches your type, you could instead add a discriminator. The below is the most basic example, and requires you to manage your own discriminators... you'd need to get deeper into the patterns to ensure you avoid duplicate discriminators.
interface A {
discriminator: 'I-AM-A';
member: string;
}
function instanceOfA(object: any): object is A {
return object.discriminator === 'I-AM-A';
}
var a: any = {discriminator: 'I-AM-A', member: "foobar"};
if (instanceOfA(a)) {
alert(a.member);
}
In TypeScript 1.6, user-defined type guard will do the job.
interface Foo {
fooProperty: string;
}
interface Bar {
barProperty: string;
}
function isFoo(object: any): object is Foo {
return 'fooProperty' in object;
}
let object: Foo | Bar;
if (isFoo(object)) {
// `object` has type `Foo`.
object.fooProperty;
} else {
// `object` has type `Bar`.
object.barProperty;
}
And just as Joe Yang mentioned: since TypeScript 2.0, you can even take the advantage of tagged union type.
interface Foo {
type: 'foo';
fooProperty: string;
}
interface Bar {
type: 'bar';
barProperty: number;
}
let object: Foo | Bar;
// You will see errors if `strictNullChecks` is enabled.
if (object.type === 'foo') {
// object has type `Foo`.
object.fooProperty;
} else {
// object has type `Bar`.
object.barProperty;
}
And it works with switch too.
Can a TypeScript type implement an interface? - Stack Overflow
How to check if a variable implements an interface in TypeScript? - Ask a Question - TestMu AI Community
Casting an object to an interface it "doesn't" implement?
Can instanceOf operator be used to check if an object is an instance of a n interface, or type?
What is a TypeScript interface?
What are the types of TypeScript interfaces?
When should I use interfaces in TypeScript?
The answer to the question as asked is no, you cannot do this directly with a type alias. An implements clause only applies to class declarations, and an extends clause only applies to interface or class declarations.
Of course it is easy enough to get analogous functionality:
An implements clause on a class just checks to see if the class instance is assignable to the declared type, and produces a compiler warning if it's not; it has no effect on the type of
the instance. You can do the same thing with a utility type like
type Implements<T, U extends T> = U
So Implements<T, U> doesn't have an effect on the resulting type, U, but since U is constrained to T, you will get a warning if it is not assignable.
Let's test it:
type Cat = Implements<IPet, {
needsFood: boolean,
color: string,
}> // okay
type Dog = Implements<IPet, {
bark(): void
}>; // error! Property 'needsFood' is missing in type '{ bark(): void; }'
Looks good.
Meanwhile an extends clause can be used to add members to or narrow members of a parent type. This is essentially the same as an intersection type, and so we can make a utility type to capture this:
type Extends<T, U extends Pick<T, keyof T & keyof U>> =
T & U;
Here we combine both the parent type T and the new members U. I've constrained U to make sure that you can't add conflicting properties, which is similar to what happens if you try to extend an interface with conflicting properties:
type Cat2 = Extends<IPet, {
color: string
}>
type Dog2 = Extends<IPet, {
needsFood: number // error!
}>; // error!
// Type '{ needsFood: number; }' does not satisfy the constraint Pick<IPet, "needsFood">.
Also looks good.
Those approaches aren't completely identical to implements/extends clauses, but they should be close enough for a lot of use cases. There are almost surely edge cases where they differ and it's possible these could be repaired or worked around. But the basic takeaway here is that you can use generic constraints and intersection types to build a solution.
Playground link to code
In TypeScript, you can indeed extend a type with an interface. The syntax for extending a type with an interface is using the extends keyword. Here's an example:
interface Shape {
color: string;
}
type Square = Shape & {
sideLength: number;
}
let square: Square = {
color: "blue",
sideLength: 10
};
This creates a new type Square that extends the Shape interface with an additional property sideLength. You can also use interfaces with classes for defining the shape of the instances of the class. Classes in TypeScript can implement interfaces to enforce that the class meets the structure defined by the interface.
So, you can use both types and classes to work with interfaces in TypeScript.