왜 반대하지 않는 거죠?키는 TypeScript에서 키 타입을 반환합니까?
제목으로 모든 것을 알 수 있습니다.Object.keys(x)TypeScript에서 유형을 반환합니다.Array<keyof typeof x>그게 바로 그거Object.keys따라서 TypeScript 정의 파일 작성자 측에서 반환 유형을 단순하게 하지 않는 것은 명백한 과실인 것 같습니다.keyof T.
그들의 GitHub repo에 버그를 기록해야 할까요, 아니면 그냥 PR을 보내 수정해야 할까요?
현재 반환 유형(string[]( )는 의도적인 것입니다.왜요?
다음과 같은 유형을 고려합니다.
interface Point {
x: number;
y: number;
}
다음과 같은 코드를 작성합니다.
function fn(k: keyof Point) {
if (k === "x") {
console.log("X axis");
} else if (k === "y") {
console.log("Y axis");
} else {
throw new Error("This is impossible");
}
}
질문 하나 하겠습니다.
적절한 타입의 프로그램에서는, 에의 법적 문의가 가능합니까?
fn에러 케이스를 조사하시겠습니까?
원하는 대답은 물론 "아니오"입니다.하지만 이게 무슨 상관이야?Object.keys?
이제 다른 코드를 생각해 보겠습니다.
interface NamedPoint extends Point {
name: string;
}
const origin: NamedPoint = { name: "origin", x: 0, y: 0 };
TypeScript의 유형 시스템에 따르면NamedPoint는 유효합니다.Points.
이제 코드를 조금 더 작성하겠습니다.
function doSomething(pt: Point) {
for (const k of Object.keys(pt)) {
// A valid call if Object.keys(pt) returns (keyof Point)[]
fn(k);
}
}
// Throws an exception
doSomething(origin);
잘 짜여진 우리 프로그램이 방금 예외를 발생시켰어요!
여기 뭔가 잘못됐어!반환함으로써keyof T부터Object.keys, 우리는 다음과 같은 가정을 위반했다.keyof T오브젝트에 대한 참조가 있다고 해서 참조 유형이 값 유형의 슈퍼타입이 아닌 것은 아니기 때문에 완전한 목록을 작성합니다.
기본적으로 다음 4가지 중 적어도 하나는 참일 수 없습니다.
keyof T의 키의 완전한 리스트입니다.T- 추가 속성이 있는 유형은 항상 기본 유형의 하위 유형입니다.
- 슈퍼타입 참조를 사용하여 하위타입 값에 별칭을 지정할 수 있습니다.
Object.keys돌아온다keyof T
폐기 포인트 1 메이킹keyof거의 쓸모가 없다, 왜냐하면 그것은 을 의미하기 때문이다.keyof Point다른 가치일 수도 있다"x"또는"y".
포인트 2를 버리면 TypeScript의 타입 시스템이 완전히 파괴됩니다.선택 사항이 아니야.
포인트 3을 버리면 TypeScript의 타입 시스템도 완전히 파괴됩니다.
포인트 4를 버리는 것은 괜찮고, 프로그래머인 여러분으로 하여금 여러분이 다루고 있는 물체가 여러분이 가지고 있다고 생각하는 것의 하위 타입의 별칭인지 아닌지 생각하게 합니다.
이를 합법적이면서도 모순되지 않게 하기 위한 "누락된 기능"은 포인트 #2의 대상이 아닌 새로운 종류의 유형을 선언할 수 있는 "Exact Types"입니다.이 기능이 존재한다면, 아마도 이 기능은Object.keys돌아가다keyof T을 위해서만T가 정확하게 선언되었습니다.
부록:확실히 일반적이지?
하는 바가 있다.Object.keys 돌아올 수 keyof T★★★★★★★★★★★★★★★★★★★★★★★★★★★츠미야★★★★★★★★★★★★★★★★★★:
class Holder<T> {
value: T;
constructor(arg: T) {
this.value = arg;
}
getKeys(): (keyof T)[] {
// Proposed: This should be OK
return Object.keys(this.value);
}
}
const MyPoint = { name: "origin", x: 0, y: 0 };
const h = new Holder<{ x: number, y: number }>(MyPoint);
// Value 'name' inhabits variable of type 'x' | 'y'
const v: "x" | "y" = (h.getKeys())[0];
또는 이 예에서는 명시적 유형 인수가 필요하지 않습니다.
function getKey<T>(x: T, y: T): keyof T {
// Proposed: This should be OK
return Object.keys(x)[0];
}
const obj1 = { name: "", x: 0, y: 0 };
const obj2 = { x: 0, y: 0 };
// Value "name" inhabits variable with type "x" | "y"
const s: "x" | "y" = getKey(obj1, obj2);
작업 중인 개체에 추가 속성이 없다고 확신할 수 있는 경우 다음과 같은 작업을 수행할 수 있습니다.
const obj = {a: 1, b: 2}
const objKeys = Object.keys(obj) as Array<keyof typeof obj>
// objKeys has type ("a" | "b")[]
원하는 경우 함수를 추출할 수 있습니다.
const getKeys = <T>(obj: T) => Object.keys(obj) as Array<keyof T>
const obj = {a: 1, b: 2}
const objKeys = getKeys(obj)
// objKeys has type ("a" | "b")[]
보너스로 여기 있습니다.Object.entriesGitHub의 문제에서 이것이 디폴트가 아닌 이유에 대한 컨텍스트를 가져옵니다.
type Entries<T> = {
[K in keyof T]: [K, T[K]]
}[keyof T][]
function entries<T>(obj: T): Entries<T> {
return Object.entries(obj) as any;
}
이것은 구글에서 가장 인기 있는 이슈이기 때문에 앞으로 나아가기 위한 도움을 드리고 싶습니다.
이 방법들은 주로 다른 답변/댓글 섹션에서 찾을 수 있는 다양한 이슈 페이지의 긴 토론에서 따온 것입니다.
예를 들어 다음과 같은 코드가 있다고 가정해 봅시다.
const obj = {};
Object.keys(obj).forEach((key) => {
obj[key]; // blatantly safe code that errors
});
다음으로 몇 가지 진행 방법을 제시하겠습니다.
를 하십시오.
.entries()★★★★★★★★★★★★★★★★★」.values()츠요시const obj = {}; Object.values(obj).forEach(value => value); Object.entries(obj).forEach([key, value] => value);도우미 기능을 만듭니다.
function keysOf<T extends Object>(obj: T): Array<keyof T> { return Array.from(Object.keys(obj)) as any; } const obj = { a: 1; b: 2 }; keysOf(obj).forEach((key) => obj[key]); // type of key is "a" | "b"타입의 재캐스팅(이 타입은 코드를 많이 재작성할 필요가 없기 때문에 큰 도움이 됩니다)
const obj = {}; Object.keys(obj).forEach((_key) => { const key = _key as keyof typeof obj; obj[key]; });
이 중 어느 것이 가장 고통스럽지 않은지는 대부분 자신의 프로젝트에 달려 있습니다.
생각할 수 있는 해결책
const isName = <W extends string, T extends Record<W, any>>(obj: T) =>
(name: string): name is keyof T & W =>
obj.hasOwnProperty(name);
const keys = Object.keys(x).filter(isName(x));
언급URL : https://stackoverflow.com/questions/55012174/why-doesnt-object-keys-return-a-keyof-type-in-typescript
'programing' 카테고리의 다른 글
| 로드 밸런서에 클라이언트에 사용 가능한 서버가 없습니다. (0) | 2023.03.08 |
|---|---|
| 각각 $.를 사용하여 Json 데이터에 대한 jquery 루프 (0) | 2023.03.08 |
| Larabel에서 최대 파일 크기를 검증하는 방법 (0) | 2023.03.03 |
| BeCalledWith()를 기대하는 개체를 전달하는 중 (0) | 2023.03.03 |
| [ AngularJS group ]체크박스 검증 (0) | 2023.03.03 |