TypeScriptでクラスを初期化するときにObjectを渡して初期化したい

はじめに

下記のようなクラスがあった場合にどうやって初期化しようかと悩んだため色々試してみました

class User {
    name: string;

    age: number;

    nickname?: string;

    public hello(): string {
        return `[${this.nickname ?? this.name}] Hello!!`;
    }
}

やったこと

先に結論ですが、最終的には下記の形に落ち着きました

// Tのpropertyの名前の列挙
type NonFunctionPropertyNames<T> = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T];

// Tのproperty
type NonFunctionProperties<T> = Pick<T, NonFunctionPropertyNames<T>>;

class User {
    name?: string = 'anonymous';

    age!: number;

    nickname?: string;

    public constructor(params: NonFunctionProperties<User>) {
        Object.assign(this, params);
    }

    public hello(): string {
        return `[${this.nickname ?? this.name}] Hello!!`;
    }
}

const user = new User({
    age: 18,
});

console.log(user.hello());
// > [anonymous] Hello!!

Partial を試してみたんですが、絶対に欲しい値もオプショナルになってしまうので要望に合いませんでした

また、単純なpropertyの列挙だとメソッドまで含まれてしまうのでメソッドを除外しています

デフォルト値も定義できるので今のところ特に困ってません

NonFunctionPropertyNames などはここを参考にしました www.typescriptlang.org