Typescript의 배열에서 작성하고 집합하는 2가지 방법
20435 단어 typescript
interface Person {
name: string;
age: number;
address: string;
};
// This is a valid 'Person' since the object contains all of the
// keys from the interface above and the types allline up.
const person: Person = {name: "shane", age: 21, address: "England"}
그러나 때때로, 우리는 낡은 인터페이스의 기초 위에서 새로운 인터페이스를 파생시켜야 하지만, 일부 키에만 한정될 수도 있다.반환된 데이터를 제한할 때 일반적으로 API 응답에서 이렇게 합니다.
간단한 예로,
name
인터페이스의 age
와 Person
필드만 포함하는 새로운 인터페이스를 만드는 방법을 보여 줍니다.새로운 유형을 파생시키다
물론 세 개의 필드만 있는 간단한 예에서는 다음과 같은 새 인터페이스를 만들어야 할 수도 있습니다.
interface Person2 {
name: string;
age: number;
};
그러나 인터페이스가 실제 코드 라이브러리에서 점점 커지는 것을 알고 있기 때문에 우리는 정말로 name
와 age
필드와 유형을 다시 사용하고 싶다.한 가지 방법은
pick
보존할 필드를 저장하는 것이다type Person2 = Pick<Person, "name" | "age">
이것은 바로 우리가 위에서 원하는 것입니다. Pick
"name" | "age"
병합된 요소를 사용하여 새로운 맵 형식을 만들기 때문입니다.이는 수동으로 작성한 내용과 같습니다.type Person2 = {[K in "name" | "age"]: Person[K]}
여기서 정말 중요한 부분은 하드코딩이 아닌 새로운 유형을 파생시키고 있다는 것이다.이것은 밑바닥 Person
인터페이스에 대한 후속 변경 사항이 우리의 전체 코드 라이브러리에 반영된다는 것을 의미한다.예를 들어
user
의 Person
속성이 object
대신 string
로 변경되면 이 변경은 새로운 Person2
유형으로 전파된다.매핑 유형이 어마어마합니다.
위에서 보듯이 기존 유형에서 새로운 유형을 파생시키는 것은 매우 강력한 개념이다. Typescript에 대한 지식이 증가함에 따라 점점 더 많은 새로운 유형을 사용할 것이다.
현재, 위의 코드 예시를 돌이켜 보면, 유니버설
"name" | "age"
을 동적 그룹으로 바꾸려면 어떤 일이 일어날까요?하나의 키를 문자열로 하고, 이 키만 포함하는 대상을 되돌려 주는 함수를 상상할 수 있습니다.
// Here's the goal: we want Typescript
// to know that `p` here is not only a subset of `Person`
// but also it ONLY contains the keys "name" & "age"
const p = getPerson(["name", "age"]);
첫 번째 방법은 필드에 string[]
를 받아들이고 되돌아오는 것일 수 있다Partial<Person>
function getPerson(fields: string[]): Partial<Person> {
// implementation omitted for brevity
return {} as any;
}
다음과 같은 두 가지 주요 문제가 있습니다.fields
매개 변수는 여기에 모든 문자열을 포함할 수 있지만, Person
인터페이스의 키만 허용할 수 있도록 범위를 좁히고 싶습니다.Partial<Person>
의 반환 형식은 모든 필드를 선택할 수 있기 때문에 유형 정보를 잃어버릴 수 있습니다.하드 코드
이 두 문제를 어떻게 해결하는지 이해하기 위해서 함수 서명을 다시 써서 우리가 예시에서 원하는 유형을 완전히 포함하도록 합니다.
function getPerson(fields: ("name" | "age")[]): Pick<Person, "name" | "age"> {
// implementation omitted for brevity
return {} as any;
}
지금은 표시 수프 같지만, 우선 fields
파라미터를 보면, 이것은 우리가 원하는 string[]
(이 유형은 모든 문자열을 포함하기 때문에) 이 아니라, 실제로는 '사람에게 존재하는 키 그룹' 일 뿐이다.이 모든 것은 Typescript가 어떻게 연합 유형을 만들고 사용하는지, 그리고 그것들을 그룹 유형과 결합시키는지 이해하는 데 관한 것이다.
// This is a "union" of 3 string literals
type KeyUnion = ("name" | "age" | "person");
// This is an Array type, where it's elements are
// restricted to those that are found in the union
// "name" | "age" | "person"
type KeyArray = ("name" | "age" | "person")[];
// Sometimes it's easier to understand in this style
type KeyArray = Array<"name" | "age" | "person">;
// Finally you can substitute the strings for the
// type alias created above
type Keys = KeyUnion[]
일부 기본적인 연합/수조 유형에 대해 말하자면, 이것은 아주 좋은 입문 지식이다. 다음 업무의 원인을 이해하기 위해 이 위치가 필요하다.그러나 현재, 우리는 하드코딩 문자열의 텍스트를 완전히 피하기를 바란다.
인터페이스의 키를 인용하는 문자열 목록을 유지하는 것은 매우 번거롭다. 다행히도 Typescript는 많은 편리한 유형이 우리를 돕는다.
// Before: hard-coded keys
type KeyUnion = ("name" | "age" | "person");
// After: a 'derived' union type based on
// the Person interface
type KeyUnion = keyof Person;
비록 이 두 개는 등효이지만 어느 것이 가장 좋은지 잘 안다.따라서 이 부분을 함수에 적용하면 다음과 같은 결과를 얻을 수 있습니다.function getPerson(fields: (keyof Person)[]): Pick<Person, keyof Person> {
// implementation omitted for brevity
return {} as any;
}
아직.
이것은 함수 호출 사이트에 형식 보안을 제공합니다. 인터페이스에 존재하지 않는 키 호출을 사용할 수 없습니다.
getPerson
// Type 'string' is not assignable to type '"name" | "age" | "address"'
getPerson(["name", "age", "location"])
위에서 말한 바와 같이 TS는 이러한 상황을 정확하게 방지했다. 왜냐하면 수조의 세 번째 요소는 Person
의 유효한 키가 아니기 때문이다.그러나 반환 유형이 닫혔습니다.
만약 우리가
mapped types
로 잠시 돌아간다면, 우리는 왜 <Pick, keyof Person>
가 우리가 원하는 것이 아닌지 쉽게 알게 될 것이다.// this creates a new type with ALL the keys in Person
Pick<Person, keyof Person>
// it's exactly the same as this, it's a 1:1 mapping
{[K in keyof Person]: Person[K]}
// Or, for even more clarity (not valid typescript though), it's like doing this
{[for K in "name" | "age" | "person"]: Person[K]}
그래서 우리는 여전히 Pick
을 원하지만, 전송된 키 그룹을 바탕으로 하나의 연합 유형을 만들어야 한다. 기본적으로 다음과 같은 내용이 필요하다.const keys = ["name"]
// -> should produce Pick<Person, "name">
const keys = ["name", "age"]
// -> should produce Pick<Person, "name" | "age">
const keys = ["name", "age", "address"]
// -> should produce Pick<Person, "name" | "age" | "address">
그룹에서 집합을 만드는 첫 번째 방법
독립된 예로 만약에 우리가 이런 유형의 단언을 한다면 우리는 다음과 같은 내용에서 문자열 텍스트의 합집합을 쉽게 얻을 수 있다.
const keys: (keyof Person)[] = ["name", "age"]
(keyof Person)[]
를 사용하여 유형을 제한하는 것은 string[]
뿐만 아니라 Typescript에 하나의 병합을 파생시킬 수 있음을 의미한다.// creates the union ("name" | "age")
type Keys = typeof keys[number]
사실이 증명하듯이, 모든 수조에서 typeof keys[number]
사용하면 Typescript로 하여금 모든 가능한 유형을 포함하는 합집합을 생성하게 할 것이다.우리의 예에서, 우리는 그룹이 인터페이스에서 온 키만 포함할 수 있다고 지적했기 때문에, Typescript는 이 정보를 사용하여 우리에게 필요한 연합을 제공한다.
명확하게 보기 위해서 아래의 방법은 통하지 않는다
const keys = ["name", "age"]
// only creates the union `string` since there's no
// type assertion after `keys`
type Keys = typeof keys[number]
수조에서 합집합을 만드는 두 번째 방법
Typescript의 연합 유형은 이렇게 많은 고급 용례를 해제하는 관건이기 때문에 시종일관 그것들을 사용하는 방법을 모색할 필요가 있다.
위에서 우리의 기능을 완성하기 위해서 우리는 실제적으로 첫 번째 예시를 사용할 것이다. 그러나 유사한 상황에 부딪히면 다른 기교를 이해하는 것이 가치가 있다.
상수 단언
비교적 새로운 특성을 사용하여 TS가 배열(및 기타 유형)을 텍스트(또는 읽기 전용) 유형으로 간주하도록 지시할 수 있습니다.
보시다시피Typescript는 다음
keys
변수의 유형string[]
을 기술적으로 정확하게 추정하지만, 우리의 용례에 있어서, 이것은 우리가 그것으로부터 연합을 만들면 가치 있는 정보를 잃게 된다는 것을 의미합니다.// to TS, this is just `string[]`...
const keys = ["name", "age"];
// ... which means this union
// type ends up with just `string`,
// which includes every single string ever :(
type Keys = typeof keys[number];
그러나 aconst assertion
를 사용하면 우리는 매우 다른 결과를 얻었다.너는 기본적으로 Typescript에 어떤 문자 형식도 확대할 수 없다고 말하고 있다.그래서
"name"
는 "name"
가 아니라 string
로 유지된다. 이것은 우리가 이전의 예로 돌아가면 Typescript에 모든 요소를 합쳐서 만들 수 있음을 의미한다.// now, TS thinks this is `readonly ["name", "age"]`
const keys = ["name", "age"] as const;
// this is now the union we wanted, "name" | "age"
type Keys = typeof keys[number];
구현 완료
마지막으로, 우리는 이 지식들을 실천에 옮깁시다.
위에서 말한 바와 같이, 우리는 Typescript를 사용하여 함수에 대한 주석을 하고자 한다. 그러면 문자열 그룹을 사용하여 함수를 호출할 때, 문자열이 인터페이스의 키 이름과 일치하는지 확인하고, 이 동적 값을 사용하여 원시 인터페이스에서 파생된 좁은 반환 형식을 만들 것이다.
// only accept keys from `Person`
// then use them to narrow a new type.
function getPerson<T extends (keyof Person)[]> (fields: T): Pick<Person, T[number]> {
// implementation omitted for brevity
return {} as any;
}
Reference
이 문제에 관하여(Typescript의 배열에서 작성하고 집합하는 2가지 방법), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/shakyshane/2-ways-to-create-a-union-from-an-array-in-typescript-1kd6텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)