Type Script에 "뒤에 생성기에 전달되지 않은 매개변수가 있어야 함"이라는 유형 제한
32918 단어 JavaScriptTypeScript타입퍼즐 유형tech
이루어지다
/**
* [α] T 型から undefined 不可キーの union を抽出
*/
type RequiredKeys<T> = {
[K in keyof T]-?: Record<any, unknown> extends Pick<T, K>
? never
: K;
}[keyof T];
/**
* [β] α を利用し, Passed 型から Req 型の条件を満たさないものだけを抽出
*/
type MissingKeys<Req, Passed extends Partial<Req>> = {
[K in keyof Pick<
Req,
RequiredKeys<Req>
>]: Passed[K] extends Req[K] ? never : K;
}[keyof Pick<Req, RequiredKeys<Req>>];
/**
* [γ] β を利用し, 「undefined 不可の不足しているサブセット」と「それ以外のサブセット」を抽出
* 後者に対してのみ undefined を許可して型を合成する
*/
type RequireMissingSubset<Req, Passed extends Partial<Req>> = Pick<
Req,
MissingKeys<Req, Passed>
> &
Partial<Omit<Req, MissingKeys<Req, Passed>>>;
/**
* γ を利用し, 可変長リストで引数自体を省略可能か表現する
*/
export type RequireMissing<Req, Passed extends Partial<Req>> =
Record<any, unknown> extends RequireMissingSubset<Req, Passed>
? [options?: RequireMissingSubset<Req, Passed>]
: [options: RequireMissingSubset<Req, Passed>];
구조기의 파라미터를 엄격하게 제어하기 위해 아래의'여분의 열쇠가 있는지 없는지'를 동시에 검사하십시오.export type Exact<T, Shape> = T extends Shape
? Exclude<keyof T, keyof Shape> extends never
? T
: never
: never;
사용법
// プロフィール作成に必要な項目
type Profile = {
name: string; // 名前(*必須*)
age: number; // 年齢(*必須*)
url?: string; // URL(任意)
description?: string; // 自己紹介(任意)
}
// ↓ コンストラクタから推論される型パラメータを与える
class ProfileFactory<O extends Partial<Profile>> {
// ↓ すべて Nullable にしておく
private readonly name: string|null;
private readonly age: number|null;
private readonly url: string|null;
private readonly description: string|null;
// ↓ 推論させる対象
constructor(options?: Exact<O, Partial<Profile>>) {
this.name = options?.name ?? null;
this.age = options?.age ?? null;
this.url = options?.url ?? null;
this.description = options?.description ?? null;
}
// ↓ 作成時に渡されなかった必須オプションを RequireMissing を用いたオーバーロードで要求
public create(...args: RequireMissing<Profile, O>): Profile;
// ↓ 実際は省略可能な Partial<Profile> 型として受け取る
public create(options?: Partial<Profile>): Profile {
return {
name: options?.name ?? this.name,
age: options?.age ?? this.age,
url: options?.url ?? this.url,
description: options?.description ?? this.description,
} as Profile; // ←アサーションが必要
}
}
// 必須パラメータはファクトリで埋められている
const factory1 = new ProfileFactory({
name: 'Bob',
age: 20,
});
// 空で作れる
factory1.create({});
// 引数自体を省略しても作れる
factory1.create();
// 部分的に必須パラメータをオーバーライドしても作れる
factory1.create({
name: 'Bob',
url: 'https://example.com/',
});
// 全部指定しても作れる
factory1.create({
name: 'Bob',
age: 20,
url: 'https://example.com/',
description: 'hello',
});
// 必須パラメータがファクトリで不足
const factory2 = new ProfileFactory({
age: 20,
});
// 足りないものを補えば作れる
factory2.create({
name: 'Bob',
});
// 部分的にオプションパラメータをオーバーライドしても作れる
factory2.create({
name: 'Bob',
url: 'https://example.com/',
});
// 全部指定しても作れる
factory2.create({
name: 'Bob',
age: 20,
url: 'https://example.com/',
description: 'hello',
});
// 空では不可
factory2.create({});
// 引数自体を省略すると不可
factory2.create();
// ファクトリに何もパラメータが与えられていない
const factory3 = new ProfileFactory();
// 必須パラメータをすべて指定すれば作れる
factory3.create({
name: 'Bob',
age: 20,
});
// 全部指定しても作れる
factory3.create({
name: 'Bob',
age: 20,
url: 'https://example.com/',
description: 'hello',
});
// 必須パラメータが足りなければ不可
factory3.create({
name: 'Bob',
url: 'https://example.com/',
});
// 空では不可
factory3.create({});
// 引数自体を省略すると不可
factory3.create();
// 余分なパラメータを与えるとコンストラクタでエラー
const factory4 = new ProfileFactory({
name: 'Bob',
age: 20,
foo: 123,
});
// 余分なパラメータは作成時にもエラー
const factory5 = new ProfileFactory({
name: 'Bob',
age: 20,
});
factory5.create({
foo: 123,
});
Playground를 통해 동작 확인 터널 말뚝 뒤가 자바스크립트에 이용된다고 가정한 경우 섣불리 결단하지 말고 실행 시 유형 검사를 꼼꼼히 적는 게 좋다.
public create(...args: RequireMissing<Profile, O>): Profile;
public create(options?: Partial<Profile>): Profile {
const name = options?.name ?? this.name;
if (name === null) {
throw new Error('Missing parameter: name');
}
const age = options?.age ?? this.age;
if (age === null) {
throw new Error('Missing parameter: age');
}
const url = options?.url ?? this.url;
const description = options?.description ?? this.description;
return { name, age, url, description };
}
Special Thanks: @uhyo 선생(개량에 협조를 받았습니다)
Reference
이 문제에 관하여(Type Script에 "뒤에 생성기에 전달되지 않은 매개변수가 있어야 함"이라는 유형 제한), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/mpyw/articles/3c063143fe884a텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)