class Point {
x: number;
y: number;
}
const pt = new Point();
pt.x = 0;
pt.y = 0;
pt.x = "0"; // Type 'string' is not assignable to type 'number'.
class BadGreeter {
name: string; //Property 'name' has no initializer and is not definitely assigned in the constructor.
}
class GoodGreeter {
name: string;
constructor() {
this.name = "hello";
}
}
// 생성자를 사용해 초기화해야할 상황이 아니면 ! 연산자를 사용
class OKGreeter {
name!: string; //ok
}
class Greeter {
readonly name: string = "world";
constructor(otherName?: string) {
if (otherName !== undefined) {
this.name = otherName;
}
}
err() {
this.name = "not ok"; //Cannot assign to 'name' because it is a read-only property.
}
}
const g = new Greeter();
g.name = "also not ok"; //Cannot assign to 'name' because it is a read-only property.
class Point {
x: number;
y: number;
constructor(x = 0, y = 0) {
this.x = x;
this.y = y;
}
// 오버로딩
constructor(x: number, y: string);
constructor(s: string);
constructor(xs: any, y?: any) {
}
class Base {
k = 4;
}
class Derived extends Base {
constructor() {
console.log(this.k); // // 'super' must be called before accessing 'this' in the constructor of a derived class.
// 먼저와야함
super();
}
}
let x: number = 0;
class C {
x: string = "hello";
m() {
// this.x로 적지 않으면 C가 있는 scope의 x=0 참조
x = "world";
Type 'string' is not assignable to type 'number'.
}
}
class C {
_length = 0;
get length() {
return this._length;
}
set length(value) {
this._length = value;
}
}
class MyClass {
[s: string]: boolean | ((s: string) => boolean);
check(s: string) {
return this[s] as boolean;
}
}
interface Pingable {
ping(): void;
}
class Sonar implements Pingable {
ping() {
console.log("ping!");
}
}
class Ball implements Pingable {
Class 'Ball' incorrectly implements interface 'Pingable'.
// Property 'ping' is missing in type 'Ball' but required in type 'Pingable'.
pong() {
console.log("pong!");
}
}
interface Checkable {
check(name: string): boolean;
}
class NameChecker implements Checkable {
check(s) { // Parameter 's' implicitly has an 'any' type.
return s.toLowercse() === "ok"; // any로 추론되기 떄문에 여기에서는 오류가 없음
}
}
interface A {
x: number;
y?: number;
}
class C implements A {
x = 0;
}
const c = new C();
c.y = 10; // Property 'y' does not exist on type 'C'.
class Animal {
move() {
console.log("Moving along!");
}
}
class Dog extends Animal {
woof(times: number) {
for (let i = 0; i < times; i++) {
console.log("woof!");
}
}
}
const d = new Dog();
d.move();
d.woof(3);
class Base {
greet() {
console.log("Hello, world!");
}
}
class Derived extends Base {
greet(name?: string) {
if (name === undefined) {
// super 사용
super.greet();
} else {
console.log(`Hello, ${name.toUpperCase()}`);
}
}
}
const d = new Derived();
d.greet();
d.greet("reader");
interface Animal {
dateOfBirth: any;
}
interface Dog extends Animal {
breed: any;
}
class AnimalHouse {
resident: Animal;
constructor(animal: Animal) {
this.resident = animal;
}
}
class DogHouse extends AnimalHouse {
// js 코드에는 영향을 주지 않음
declare resident: Dog;
constructor(dog: Dog) {
super(dog);
}
}
class Base {
name = "base";
constructor() {
console.log("My name is " + this.name);
}
}
class Derived extends Base {
name = "derived";
}
const d = new Derived(); // 원래 클래스의 생성자가 생성될 때 "My name is base" 출력
class Greeter {
public greet() {
console.log("hi!");
}
}
const g = new Greeter();
g.greet();
class Greeter {
public greet() {
console.log("Hello, " + this.getName());
}
protected getName() {
return "hi";
}
}
class SpecialGreeter extends Greeter {
public howdy() {
// OK to access protected member here
console.log("Howdy, " + this.getName());
}
}
const g = new SpecialGreeter();
g.greet();
// Property 'getName' is protected and only accessible within class 'Greeter' and its subclasses.
g.getName();
class Base {
protected m = 10;
}
class Derived extends Base {
m = 15; // 따로 public 기호를 적지 않더라도 public이 됨에 주의
}
const d = new Derived();
console.log(d.m); //가능
class Base {
protected x: number = 1;
}
class Derived1 extends Base {
protected x: number = 5;
}
class Derived2 extends Base {
f1(other: Derived2) {
other.x = 10;
}
f2(other: Base) {
/*Property 'x' is protected and only accessible through an instance of
class 'Derived2'. This is an instance of class 'Base'. */
other.x = 10;
}
}
class Base {
private x = 0;
}
const b = new Base();
console.log(b.x); // Property 'x' is private and only accessible within class 'Base'.
class Derived extends Base {
showX() {
console.log(this.x); // Property 'x' is private and only accessible within class 'Base'.
}
}
class A {
private x = 10;
public sameAs(other: A) {
return other.x === this.x; //ok
}
}
class MySafe {
private secretKey = 12345;
}
const s = new MySafe();
//Property 'secretKey' is private and only accessible within class 'MySafe'.
console.log(s.secretKey);
// ok
console.log(s["secretKey"]);
class MyClass {
static x = 0;
private static y = 1;
static printX() {
console.log(MyClass.x);
}
}
console.log(MyClass.x);
MyClass.printX();
console.log(MyClass.y); // Property 'y' is private and only accessible within class 'MyClass'.
class Base {
static getGreeting() {
return "Hello world";
}
}
class Derived extends Base {
myGreeting = Derived.getGreeting();
}
// name, length, call 사용 불가능
class S {
// Static property 'name' conflicts with built-in property 'Function.name' of constructor function 'S'.
static name = "S!";
}
// 이렇게 사용하지 말 것
class MyStaticClass {
static doSomething() {}
}
// 함수를 직접 선언하거나
function doSomething() {}
// 평범한 객체로 선언할 것
const MyHelperObject = {
dosomething() {},
};
class Foo {
static #count = 0;
get count() {
return Foo.#count;
}
static {
try {
const lastInstances = loadLastInstances();
Foo.#count += lastInstances.length;
}
catch {}
}
}
class Box<Type> {
contents: Type;
constructor(value: Type) {
this.contents = value;
}
}
const b = new Box("hello!"); // Box<String>
// static 프로퍼티에는 사용이 불가능함
class Box<Type> {
static defaultValue: Type; //Static members cannot reference class type parameters.
}
class MyClass {
name = "MyClass";
getName() {
return this.name;
}
}
const c = new MyClass();
const obj = {
name: "obj",
getName: c.getName, // == func () {return this.name;}
};
const letError = c.getName
// this = obj
console.log(obj.getName()); //obj
// this = window => this.name = undefined
console.log(letError()); //Cannot read properties of undefined (reading 'name')
class MyClass {
name = "MyClass";
getName = () => {
return this.name; // This: Myclss로 고정
};
}
const c = new MyClass();
const g = c.getName;
console.log(g()); // MyClass
class MyClass {
name = "MyClass";
getName(this: MyClass) {
return this.name;
}
}
const c = new MyClass();
c.getName(); //MyClass
// this !== MyClass => 에러 발생
const g = c.getName;
console.log(g()); // The 'this' context of type 'void' is not assignable to method's 'this' of type 'MyClass'.
class Box {
contents: string = "";
set(value: string) { // (value: string) => this
this.contents = value;
return this;
}
}
class Box {
content: string = "";
sameAs(other: this) {
return other.content === this.content;
}
}
class DerivedBox extends Box {
otherContent: string = "?";
}
// 같은 클래스로 생성된 인스턴스끼리만 this 타입 할당 가능
const base = new Box();
const derived = new DerivedBox();
/*
Argument of type 'Box' is not assignable to parameter of type 'DerivedBox'.
Property 'otherContent' is missing in type 'Box' but required in type 'DerivedBox'.
*/
derived.sameAs(base);
class FileSystemObject {
isFile(): this is FileRep {
return this instanceof FileRep;
}
isDirectory(): this is Directory {
return this instanceof Directory;
}
isNetworked(): this is Networked & this {
return this.networked;
}
constructor(public path: string, private networked: boolean) {}
}
class FileRep extends FileSystemObject {
constructor(path: string, public content: string) {
super(path, false);
}
}
class Directory extends FileSystemObject {
children: FileSystemObject[];
}
interface Networked {
host: string;
}
const fso: FileSystemObject = new FileRep("foo/bar.txt", "foo");
if (fso.isFile()) {
fso.content; //FileRep
} else if (fso.isDirectory()) {
fso.children; //Directory
const fso: Directory
} else if (fso.isNetworked()) {
fso.host; //Networked & FileSystemObject
}
const someClass = class<Type> {
content: Type;
constructor(value: Type) {
this.content = value;
}
};
const m = new someClass("Hello, world"); //someClass<string>
abstract class Base {
abstract getName(): string;
printName() {
console.log("Hello, " + this.getName());
}
}
//concrete : 클래스 내부에 추상 멤버를 가지지 않는 경우
const b = new Base(); // Cannot create an instance of an abstract class.
// Non-abstract class 'Derived' does not implement inherited abstract member 'getName' from class 'Base'.
class Derived extends Base {
}
class Derived extends Base {
getName() {
return "world";
}
}
const d = new Derived();
d.printName();
function greet(ctor: typeof Base) {
const instance = new ctor(); // Cannot create an instance of an abstract class.
instance.printName();
}
function greet(ctor: new () => Base) {
const instance = new ctor();
instance.printName();
}
greet(Derived);
/*
Argument of type 'typeof Base' is not assignable to parameter of type 'new () => Base'.
Cannot assign an abstract constructor type to a non-abstract constructor type.
*/
greet(Base);
class Point1 {
x = 0;
y = 0;
}
class Point2 {
x = 0;
y = 0;
}
const p: Point1 = new Point2(); //ok
class Person {
name: string;
age: number;
}
class Employee {
name: string;
age: number;
salary: number;
}
const p: Person = new Employee(); //ok
class Empty {}
function fn(x: Empty) {
}
// 전부 가능
fn(window);
fn({});
fn(fn);
출처:
https://www.typescriptlang.org/docs/handbook/2/classes.html#extends-clauses