abstract class Person {
    name: string;

    constructor(name: string) {
        this.name = name;
    }
}

const person = new Person();//Error

abstract class Person {
    name: string;

    constructor(name: string) {
        this.name = name;
    }

    abstract greeting(): string;
}

class Employee extends Person {
    role: string;
    constructor(name: string, role: string) {
        super(name);
        this.role = role;
    }

    greeting(): string {
        return `Hello ${this.name}! You're a Microsoft ${this.role}.`;
    }
}

const employee: Person = new Employee("Sylvain", "PFE");
console.log(employee.greeting());//Hello Sylvain! You're a Microsoft PFE.

interface Logger {
    debug(message: string): void;
}

class ConsoleLogger implements Logger {
    debug(message: string): void {
        console.debug(message);
    }
}

interface Person {
    name: string;
}

interface Entity {
    id: string;
}

interface Employee extends Person, Entity {
    pin: number;
}

const duck = {
    fly: () => console.log("I can fly!"),
    swim: () => console.log("I can swim!"), 
    walk: () => console.log("I can walk!"),
    feather: true
};

 const dog = {
    swim: () => console.log("I can swim!"),
    walk: () => console.log("I can walk!"),
    fur: true
};

 const isDuck = function(obj) {
    return obj.hasOwnProperty("feather") 
            && obj.fly 
            && obj.swim
            && obj.walk;
}

if(isDuck(duck)) {
    (duck).fly();
}

if(!isDuck(dog)) {
    console.log("Not a Duck...")
}

interface Employee {
    name: string;
    role: string;
}

function greeting(employee: Employee): string {
    return `Hello ${employee.name}! You're a Microsoft ${employee.role}.`;
}

const employee = {
    name: "Sylvain", 
    role: "PFE"
};
console.log(greeting(employee));//Hello Sylvain! You're a Microsoft PFE.

interface Employee {
    name: string;
    age?: number;
}

function greeting(employee: Employee): string {
    return `Hello ${employee.name}! ${
        employee.age 
        ? `You're ${employee.age} years old.`
        : "There is no age limit to understand this example :)"
    }`;
}

console.log(greeting({ name: "Satya" }));
//Hello Satya! There is no age limit to understand this example :)
console.log(greeting({ name: "Bill", age: 62 }));
//Hello Bill! You're 62 years old.

Autres détails, un membre d’une interface peut être déclaré en lecture seule :

interface Person {
    readonly name: string;
}

const person: Person = {
    name: "Bill"
};
person.name = "Satya"//Error

const greeting = function(name: string): string {
    return `Hello ${ name }!`;
}

console.log(greeting instanceof Object);//true

interface Greeting {
    (name: string): string;
}

interface Person {
    name: string;
    isCeo: boolean;
}

interface Filter {
    (person: Person): boolean
}

function search(persons: Person[], filter: Filter): Person[] {
    const filteredPersons: Person[] = [];
    persons.forEach(function(person) {
        if(filter(person)) {
            filteredPersons.push(person);
        }
    });
    return filteredPersons;
}

const isNotCeo = function(person: Person): boolean {
    return !person.isCeo;
}

const startWithC = function(person: Person): boolean {
    return person.name.charAt(0).toUpperCase() === "C";
}

const employees: Person[] = [
    { name: "Satya", isCeo: true },
    { name: "Sylvain", isCeo: false },
    { name: "Sébastien", isCeo: false },
    { name: "Christopher", isCeo: false }
] 

const notCeoEmployees = search(employees, isNotCeo);
console.log(notCeoEmployees);
//[ { name: 'Sylvain', isCeo: false },
//  { name: 'Sébastien', isCeo: false },
//  { name: 'Christopher', isCeo: false } ]

const nameStartWithC = search(employees, startWithC);
console.log(nameStartWithC); 
//[ { name: 'Christopher', isCeo: false } ]

const notCeoEmployees = search(employees, (person) => !person.isCeo);
console.log(notCeoEmployees);
//[ { name: 'Sylvain', isCeo: false },
//  { name: 'Sébastien', isCeo: false },
//  { name: 'Christopher', isCeo: false } ]

interface Entity<T> {
    id: T; 
}

const entity: Entity<number> = {
    id: 1
};
entity.id = "1";//Erreur

class Person<T> {
    id: T;

    constructor(id: T) {
        this.id = id;
    }
}

class Person<T> implements Entity<T> {
    id: T;

    constructor(id: T) {
        this.id = id;
    }
}

class Person<T> implements Entity<number> {
    id: number;

    constructor(id: number) {
        this.id = id;
    }
}

class Values {
    add<T>(value: T): void {
        //Do something here
    }
}

const values = new Values();
values.add<number>(1);
values.add<string>("A value");
values.add(true);// Type inference works!
values.add<string>(1);//Error

 
interface Person {
    name: string;
}

function greeting<T extends Person>(person: T): string {
    return `Hello ${ person.name } !`; 
}

interface Person {
    name: string;
}

class Employee implements Person {
    company: string = "Microsoft";
    name: string = "";
}

class Factory<T> {
    private readonly ctor: new () => T
    constructor(ctor: new () => T) {
        this.ctor = ctor;
    }

    getInstance(): T {
        return new this.ctor();
    }
}

const personFactory = new Factory<Person>(Employee);

const person = personFactory.getInstance();
person.name = "Sylvain";
console.log(person);//Employee { company: 'Microsoft', name: 'Sylvain' }