TypeScript에서 함수에 대한 시그니쳐

속성을 거지는 함수 타입 정의 (정확히는 호출 시그니처(call signature))

type FunctionWithProperties = {
  (someArg: number): boolean;

  description: string;
};

function doSomething(fn: FunctionWithProperties) {
  console.log(fn.description + ": 결과 = " + fn(6));
}

// 함수 생성
const isGreaterThanFive: FunctionWithProperties = (num: number) => {
  return num > 5;
};

// 속성 추가
isGreaterThanFive.description = "5보다 큰지 확인하는 함수";


// 함수 호출
doSomething(isGreaterThanFive);

클래스의 생성자에 대한 함수 타입 정의 (정확히는 생성자 시그니처(construct signature))

type SomeConstructor = {
  new (s: string): MyClass;
};

function fn(ctor: SomeConstructor) {
  return new ctor("hello");
}

class MyClass {
  field: string = "hello";

  constructor(message: string) {
    console.log("constructor called:", message);
  }
}

const a = fn(MyClass);
console.log(a.field);

위의 2가지 요소를 조합해 보면….

interface CallOrConstruct {
  new (s: string): Date;
  (n?: number): number;
}

// 함수 객체 생성
const callOrConstruct: CallOrConstruct = function (n?: number): number {
  return n ?? 0;
} as CallOrConstruct;

// 생성자 동작 추가
callOrConstruct.prototype = Date.prototype;

// 일반 함수처럼 호출
const result = callOrConstruct(100);

console.log(result); // 100

// 생성자처럼 호출
const date = new callOrConstruct("2026-07-16");

console.log(date);
console.log(date instanceof Date);

Symbol.toPrimitive를 이용한 객체의 원시값 변환 제어

객체 자체에 대한 적절한 원시값으로 변환하고자 할때 Symbol.toPrimitive가 매우 유용하게 사용될 수 있습니다.

다음과 같은 코드가 있다면 …

const money = {
    amount: 1000,

    [Symbol.toPrimitive](hint) {
        if (hint === "number") {
            return this.amount;
        }

        return `${this.amount}원`;
    }
};

위의 money에 대해 다음 코드를 실행해 보면 상황에 맞게 해당 객체가 알맞은 원시값으로 변환되어 사용됩니다.

console.log(+money);     // 1000
console.log(`${money}`); // 1000원

Symbol.iterator를 이용한 for … of 지원하기

데이터를 가지고 있는 컨테이너 객체에 대해 for … of 를 지원하기 위해서는 Symbol.iterator가 필요합니다.

예를들어 1, 2, 3 데이터를 가지고 있는 다음과 같은 객체가 있다고 할때 for … of로 데이터를 순회한다면 참 직관적입니다.

const numbers = {
    data: [1, 2, 3]
};

for (const n of numbers) {
    console.log(n);
}

위의 코드가 실행될 수 있으려면 다음과 같은 코드를 추가해야 합니다.

const numbers = {
    data: [1, 2, 3],

    [Symbol.iterator]() {
        let index = 0;
        const data = this.data;

        return {
            next() {
                if (index < data.length) {
                    return {
                        value: data[index++],
                        done: false
                    };
                }

                return {
                    done: true
                };
            }
        };
    }
};

three.js의 WebGLRenderer 객체의 생성에 대한 권장 방식이 변경됨

기존에 WebGLRenderer 객체를 생성하기 위한 코드는 다음과 같았습니다.

import * as THREE from "three"

...

let renderer = new THREE.WebGLRenderer({ antialias: true });

위의 방식 대신에 다음 방식이 권장됩니다.

import * as THREE from "three/webgpu"
import { WebGLRenderer } from 'three'

...

let renderer = new WebGLRenderer({ antialias: true });

권장되는 방식의 경우 WebGL에서도 TSL을 사용할 수 있습니다. 단, 다음과 같은 추가적인 코드가 필요합니다.

import { WebGLNodesHandler } from 'three/addons/tsl/WebGLNodesHandler.js'

...

renderer.setNodesHandler(new WebGLNodesHandler());

실제로 WebGL 환경에서 TSL에 대한 예시 코드는 다음과 같습니다.

import { mx_fractal_noise_float, positionLocal, Fn } from 'three/tsl';

const geometry = new THREE.TorusKnotGeometry(1, 0.4, 128, 32);
const material = new THREE.MeshStandardNodeMaterial({
  color: 0x00ffff,
  metalness: .9,
});

const roughnessNode = mx_fractal_noise_float(positionLocal.mul(2), 6, 4, .7, 2).sin();

material.roughnessNode = roughnessNode;

const torusKnot = new THREE.Mesh(geometry, material);
this._scene.add(torusKnot);

위 코드에 대한 실행 결과는 다음과 같습니다.

TypeScript(또는 JavaScript)에서의 깊은 복사

GoF의 Prototype 패턴으로 예시 코드를 들어보면 다음과 같습니다.

class User {
    constructor(
        public name: string,
        public hobbies: string[],
        public settings: Map<string, any>
    ) {}

    clone(): User {
        const copy = Object.create(
            Object.getPrototypeOf(this)
        );

        Object.assign(
            copy,
            structuredClone(this)
        );

        return copy;
    }
}

clone 매서드에 깊은 복사에 대한 코드가 언급되고 있습니다. 9번 라인의 코드가 매서드에 대한 복사, 13번 라이의 코드가 속성에 대한 깊은 복사입니다. 매서드를 가진 객체의 복사에서는 이 두가지에 대한 복사가 반드시 필요합니다.