programing

TypeScript: 객체.키 반환 문자열[ ]

powerit 2023. 3. 19. 19:33
반응형

TypeScript: 객체.키 반환 문자열[ ]

「」를 사용하고 Object.keys(obj) 은 " " 입니다string[]단, 나는 그것을 원한다.(keyof obj)[].

const v = {
    a: 1,
    b: 2
}

Object.keys(v).reduce((accumulator, current) => {
    accumulator.push(v[current]);
    return accumulator;
}, []);

에러가 발생했습니다.

유형 '{ a: number; b: number; }'에 인덱스 서명이 없으므로 요소에 암시적으로 '임의' 형식이 있습니다.

3.과 TypeScript 3.1 »strict: true. Playground : 여기, 체크박스를 모두 켜주세요.Optionsstrict: true.

Object.keys를 반환하다string[]이것은, 호에서 설명한 대로 설계되어 있습니다.

이것은 의도적인 것이다.TS의 타입은 오픈 엔드로 되어 있습니다.따라서 keysof는 실행 시 얻을 수 있는 모든 속성보다 작을 수 있습니다.

몇 가지 해결책이 있습니다.가장 간단한 방법은 유형 어설션만 사용하는 것입니다.

const v = {
    a: 1,
    b: 2
};

var values = (Object.keys(v) as Array<keyof typeof v>).reduce((accumulator, current) => {
    accumulator.push(v[current]);
    return accumulator;
}, [] as (typeof v[keyof typeof v])[]);

도 있습니다.keysObject원하는 유형을 반환합니다.

export const v = {
    a: 1,
    b: 2
};

declare global {
    interface ObjectConstructor {
        typedKeys<T>(obj: T): Array<keyof T>
    }
}
Object.typedKeys = Object.keys as any

var values = Object.typedKeys(v).reduce((accumulator, current) => {
    accumulator.push(v[current]);
    return accumulator;
}, [] as (typeof v[keyof typeof v])[]);

Titian Cernicova-Dragomir의 답변 및 코멘트를 기반으로 합니다.

객체에 추가 속성이 없는 경우에만 유형 어설션을 사용하십시오(객체 리터럴은 해당되지만 개체 매개 변수는 해당되지 않음).

명시적 주장

Object.keys(obj) as Array<keyof typeof obj>

숨김 어설션

const getKeys = Object.keys as <T extends object>(obj: T) => Array<keyof T>

getKeysObject.keysgetKeys「」의 입니다.Object.keys단, 반환은 문자 그대로 입력되어 있습니다.

토론

TypeScript의 핵심 원칙 중 하나는 유형 체크는 값이 가진 모양에 초점을 맞춘다는 것입니다(참조).

interface SimpleObject {
   a: string 
   b: string 
}

const x = {
   a: "article", 
   b: "bridge",
   c: "Camel" 
}

x의 이 있다SimpleObject모の모, '이', '이', '이', '이', '이', '.SimpleObject 이 성질을 있다는 있습니다.a ★★★★★★★★★★★★★★★★★」b 그 또 다른 수 있습니다.

const someFunction = (obj: SimpleObject) => {
    Object.keys(obj).forEach((k)=>{
        ....
    })
}

someFunction(x)

디폴트로 [Object]를 입력하면 어떻게 되는지 알아보겠습니다."문자 그대로" OP가 원하는 키:

게 예요.typeof k"a"|"b"를할 때 실제 입니다.a,b,c. typescript는 k를 문자열로 입력하여 이러한 오류로부터 보호합니다.

알고 있으면obj에는 리터럴형 어설션을 사용할 수 있는 추가 속성이 없습니다.

1. npm install ts-extras )

  1. 사용방법:
import { objectKeys } from 'ts-extras'
objectKeys(yourObject)

바로 그겁니다.

====

제가 알기 또 .ts-extras:

npm install object-typed --save
import { ObjectTyped } from 'object-typed'

ObjectTyped.keys({ a: 'b' })

유형 됩니다.['a']

https://github.com/microsoft/TypeScript/issues/20503 를 참조해 주세요.

declare const BetterObject: {
  keys<T extends {}>(object: T): (keyof T)[]
}

const icons: IconName[] = BetterObject.keys(IconMap)

키 유형을 유지하다string[]

타이프스크립트 팀의 결정에 전적으로 반대합니다
논리에 , 「」는 「」라고 하는 것입니다.Object.values런타임에 속성을 추가할 수 있기 때문에 항상 any를 반환해야 합니다.

적절한 방법은 옵션 속성으로 인터페이스를 만들고 그 속성을 설정(또는 설정하지 않음)하는 입니다.

그래서 그냥 로컬에서 오버로잉을 해서ObjectConstructor다음의 내용을 포함한 선언 파일(일명 「whattery.d.ts」)을 프로젝트에 추가해 주세요.


declare interface ObjectConstructor extends Omit<ObjectConstructor, 'keys' | 'entries'> {
    /**
     * Returns the names of the enumerable string properties and methods of an object.
     * @param obj Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
     */
    keys<O extends any[]>(obj: O): Array<keyof O>;
    keys<O extends Record<Readonly<string>, any>>(obj: O): Array<keyof O>;
    keys(obj: object): string[];

    /**
     * Returns an array of key/values of the enumerable properties of an object
     * @param obj Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
     */
    entries<T extends { [K: Readonly<string>]: any }>(obj: T): Array<[keyof T, T[keyof T]]>
    entries<T extends object>(obj: { [s: string]: T } | ArrayLike<T>): [string, T[keyof T]][];
    entries<T>(obj: { [s: string]: T } | ArrayLike<T>): [string, T][];
    entries(obj: {}): [string, any][];
}

declare var Object: ObjectConstructor;

주의:

기본 유형(개체)의 Object.keys/Object.entries는 일반 문자열[] 및 [string, any][] 대신 never[] 및 [never, never][]를 반환합니다.해결책을 아시는 분은 댓글로 알려주세요.제 답변을 수정하겠습니다.

const a: {} = {};
const b: object = {};
const c: {x:string, y:number} = { x: '', y: 2 };

// before
Object.keys(a) // string[]
Object.keys(b) // string[]
Object.keys(c) // string[]
Object.entries(a) // [string, unknown][]
Object.entries(b) // [string, any][]
Object.entries(c) // [string, string|number][]

// after
Object.keys(a) // never[]
Object.keys(b) // never[]
Object.keys(c) // ('x'|'y')[]
Object.entries(a) // [never, never][]
Object.entries(b) // [never, never][]
Object.entries(c) // ['x'|'y', string|number][]

그러니까 이걸 주의해서 쓰세요

Extract 유틸리티 유형을 사용하면 파라미터가keysobj스트링(부호화 중 숫자/부호화 중 무시)입니다.

const obj = {
  a: 'hello',
  b: 'world',
  1: 123 // 100% valid
} // if this was the literal code, you should add ` as const` assertion here

// util
type StringKeys<objType extends {}> = Array<Extract<keyof objType, string>>

// typedObjKeys will be ['a', 'b', '1'] at runtime
// ...but it's type will be Array<'a' | 'b'>
const typedObjKeys = Object.keys(obj) as StringKeys<typeof obj>

typedObjKeys.forEach((key) => {
  // key's type: 'a' | 'b'
  // runtime: 'a', 'b', AND '1'
  const value = obj[key]
  // value will be typed as just `string` when it's really `string | number`
})

대부분의 개발자들은 숫자를 키로 하는 것은 잘못된 설계 결정/버그 수정이라고 생각할 것입니다.

여기 제가 사용하는 문양이 있습니다.이것은 문자열 축소를 사용하기 때문에 컴파일러는 키가 실제로 유형이라고 추론할 수 있습니다.이는 클래스에서 시연되었지만 동일한 모양의 인터페이스 또는 익명 유형과 함께 또는 상호 작용합니다.

그것은 다소 장황하지만, 거의 틀림없이 받아들여진 대답보다 더 직설적이다.여러 곳에서 복사 작업을 수행해야 하는 경우 입력이 저장됩니다.

원하는 유형이 일치하지 않으면 오류가 발생하지만 에 누락된 필드가 있는 경우 오류가 발생하지 않습니다.thingNum따라서 이는 Object.keys에 비해 단점일 수 있습니다.


    class thing {
    a: number = 1;
    b: number = 2;
    }
    type thingNum = 'a' | 'b';
    const thingNums: thingNum[] = ['a', 'b'];
    
    const thing1: thing = new thing();
    const thing2: thing = new thing(); 
...
    
    thingNums.forEach((param) => {
        thing2[param] = thing1[param];
    });

놀이터 링크

보다 정확한 유틸리티 함수는 다음과 같습니다.

const keys = Object.keys as <T>(obj: T) =>
    (keyof T extends infer U ? U extends string ? U : U extends number ? `${U}` : never : never)[];

설명:keyof T확장string | number | symbol,하지만Object.keys생략하다symbol키와 반환number키를 문자열로 사용합니다.템플릿 리터럴을 사용하여 숫자 키를 문자열로 변환할 수 있습니다.`${U}`.

이것을 사용하여keys유틸리티:

const o = {
    x: 5,
    4: 6,
    [Symbol('y')]: 7,
};
for(const key of keys(o)) {
    // key has type 'x' | '4'
}

가능한 해결책으로 다음 방법을 사용하여 반복할 수 있습니다.for..in오브젝트 위에:

for (const key in myObject) {
  console.log(myObject[key].abc); // works, but `key` is still just `string`
}

말씀하신 대로 이 방법은 작동하지 않습니다.

for (const key of Object.keys(myObject)) {
  console.log(myObject[key].abc); // doesn't!
}

언급URL : https://stackoverflow.com/questions/52856496/typescript-object-keys-return-string

반응형