불행히도 TypeScript 제네릭 에 대한 암시 적 키 및 값 유형 관계 전달 질문에 대한 훌륭한 답변 은 현재 질문의 문제를 다루지 않습니다. generateInputsAccessObject
해당 질문의 대상 함수 인에서는 하위 유형 종속 속성을 사용하지 않습니다.
실제로 위의 질문은 암시 적 키와 값 유형 관계를 제목 인 TypeScript 제네릭에 전달하지 않고 해결되었지만 이제 더 이상 피할 수 없다고 생각합니다.
다음 과 같은 EntitySpecification
일반 유형 인을 작성하십시오 ProductSpecification
.
properties
의 유형은 색인화되지 않아야합니다 . 그것은 타이프 라이터 컴파일러는 무엇을 알고 있어야한다는 것을 의미 ID
와 price
존재하지 않는 - 존재하지만, 다른 키가.properties
반복 가능 Object.entires("ProductSpecification.properties")
해야합니다 (작동해야 함).ID
그리고 price
다른 유형을 가질 수 있지만, 우리가 호출 할 때 EntitySpecification.properties.ID
나 EntitySpecification.properties.price
, 타이프 라이터 컴파일러는 유형을 알고 있어야합니다.
export type Product = {
ID: string;
price: number;
};
const ProductSpecification: EntitySpecification<keyof Product> = {
name: "Product",
properties: {
ID: {
type: DataTypes.string,
emptyStringIsAllowed: false
},
price: {
type: DataTypes.number,
numberSet: NumbersSets.nonNegativeInteger
}
}
};
여기:
export enum DataTypes {
number = "NUMBER",
string = "STRING"
}
export enum NumbersSets {
naturalNumber = "NATURAL_NUMBER",
nonNegativeInteger = "NON_NEGATIVE_INTEGER",
negativeInteger = "NEGATIVE_INTEGER",
negativeIntegerOrZero = "NEGATIVE_INTEGER_OR_ZERO",
anyInteger = "ANY_INTEGER",
positiveDecimalFraction = "POSITIVE_DECIMAL_FRACTION",
negativeDecimalFraction = "NEGATIVE_DECIMAL_FRACTION",
decimalFractionOfAnySign = "DECIMAL_FRACTION_OF_ANY_SIGN",
anyRealNumber = "ANY_REAL_NUMBER"
}
export type StringSpecification = {
readonly type: DataTypes.string;
readonly emptyStringIsAllowed: boolean;
};
export type NumberSpecification = {
readonly type: DataTypes.number;
readonly numberSet: NumbersSets;
};
물론 EntitySpecification
키를 미리 알지 못하지만 키 수는 임의적으로 클 수 있습니다 (현재의 경우 2가 아님 ProductSpecification
).
아래 솔루션은 처음 두 목표를 충족합니다.
export type EntitySpecification<Keys extends string> = {
readonly name: string;
readonly properties: { [key in Keys]: StringSpecification | NumberSpecification };
};
여기 갈등 상황, 세 번째 조건 위반의 결과 :
type StringValidationRules = {
emptyStringIsAllowed: boolean;
};
const ID_ValidationRules: StringValidationRules = {
emptyStringIsAllowed: ProductSpecification__EXPERIMENTAL.properties.ID.emptyStringIsAllowed;
}
TypeScript ID
는 StringSpecification
유형 이있는 것을 모르기 때문에 다음과 같은 오류가 있습니다.
TS2339: Property 'emptyStringIsAllowed' does not exist on type 'StringSpecification | NumberSpecification'. Property 'emptyStringIsAllowed' does not exist on type 'NumberSpecification'.
객체 유형 EntitySpecification
의 속성 키 유형 만 매핑하는 것처럼 보이지만 해당 값 유형 도 매핑해야합니다 . 이 경우 키뿐만 아니라 전체 객체 유형을 전달하는 것이 가장 좋습니다. 그런 다음 일부 매핑 구조를 통해 속성 유형을 매핑 할 수 있으며 지금처럼 키 매핑을 계속할 수 있습니다.
다음은 필요한 매핑 구조를 나타내는 한 가지 방법입니다.
type DataMapping =
{ type: number, specification: NumberSpecification }
| { type: string, specification: StringSpecification }
어디에서도 실제 유형 값 을 사용할 계획이 없습니다 DataMapping
. 컴파일러가 속성 유형을 사양 인터페이스에 연결하는 데 사용할 수있는 유형 정의 일뿐입니다.
이제 EntitySpecification
다음과 같이 정의 할 수 있습니다.
type EntitySpecification<T extends Record<keyof T, DataMapping["type"]>> = {
readonly name: string;
readonly properties: { [K in keyof T]: Extract<DataMapping, { type: T[K] }>['specification'] };
};
내가하고 있습니다 제약 T
그의 재산 유형에서 언급되는 객체 유형으로 type
의 재산입니다 DataMapping
. 이것은 Product
누구의 속성 유형이 number
및 만 string
허용하지만 (현재) 해당 사양이 {oops: boolean}
없기 때문에 같은 것을 허용 boolean
하지 않습니다.
properties
속성이있다 맵형 키가있는 K
의 키와 동일한 T
값을 가지는에서 해당 속성 타입으로부터 변환된다 (이전에 수행 된 바와 같이)와 T
즉 T[K]
.
특정 속성 매핑은입니다 Extract<DataMapping, {type: T[K]}>['specification']
. Extract
유틸리티 유형 을 사용하여 속성이 인 DataMapping
공용체 의 멤버를 선택한 다음 해당 멤버 에서 속성 을 반환합니다 .type
T[K]
specification
그것이 어떻게 작동하는지 보자 Product
:
type Product = {
ID: string;
price: number;
};
type ProductSpecification = EntitySpecification<Product>;
/* type ProductSpecification = {
readonly name: string;
readonly properties: {
ID: StringSpecification;
price: NumberSpecification;
};
} */
그게 당신이 원했던 것 같아요. 당신이 값이있는 경우 p
유형을 ProductSpecification
다음 p.properties.ID
형식이어야 StringSpecification
하고, p.properties.price
유형이어야합니다 NumberSpecification
. 만세!
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다