Typescript: 제안된 ES Rest/Spread 속성 지원

에 만든 2015년 02월 21일  ·  96코멘트  ·  출처: microsoft/TypeScript

es7 제안 : https://github.com/sebmarkbage/ecmascript-rest-spread

스프레드 속성

타자

내 생각에 이 방법의 목표는 개체를 복제하고 일부 소품을 변경할 수 있는 것이므로 이 경우 중복 속성 선언을 확인하지 않는 것이 특히 중요하다고 생각합니다.

var obj = { x: 1, y: 2};
var obj1 = {...obj, z: 3, y: 4}; // not an error

내 작은 jsx-typescript 포크에 유사한 기능( JSXSpreadAttribute )에 대한 매우 순진한 유형 검사 알고리즘 이 있습니다. 스프레드 개체를 만났을 때 속성 테이블에서 _spread 개체_의 속성을 복사합니다. , 비슷한 이름의 선언이 있는 경우 해당 속성을 재정의합니다.

방출

jstransformObject.assign 하고 babel 은 shim을 도입합니다.

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

ObjectConstructor 인터페이스에 assign 함수를 강제로 추가하거나 유사한 함수(다른 이름으로)를 제공할 수 있습니다.

최적의 솔루션은 es6 대상(또는 Object.assign 이 정의된 경우)에 도우미를 내보내지 않고 es5 , es3 대한 도우미 함수를 내보내는 것입니다

var obj = { x: 1, y: 2};
var obj1 = {...obj, z: 3};

/// ES6 emit
var obj = {x: 1, y: 2};
var obj1= Object.assign({}, obj, { z: 3 });

//ES3 emit
var __assign = function (target) { 
    for (var i = 1; i < arguments.length; i++) { 
        var source = arguments[i]; 
        for (var key in source) { 
            if (Object.prototype.hasOwnProperty.call(source, key)) { 
                target[key] = source[key];
            } 
        } 
    } 
    return target; 
};

var obj = {x: 1, y: 2};
var obj1= __assign({}, obj, { z: 3 });

휴식 속성

타자

단순 객체의 경우 새 유형은 나머지 속성 이전에 캡처된 속성을 포함하지 않는 할당의 하위 유형입니다.

var obj = {x:1, y: 1, z: 1};
var {z, ...obj1} = obj;
obj1// {x: number; y:number};

구조 해제 할당에 인덱스 선언이 있는 경우 결과에도 유사한 인덱스 선언이 있습니다.

var obj: { [string: string]: string };
var {[excludedId], ...obj1} = obj;
obj1// { [string: string]: string };

new/call 선언은 분명히 캡처되지 않습니다.

var obj: { (): void; property: string};
var { ...obj1} = obj;
obj1// { property: string };

방출

도우미 함수 없이는 _rest properties_를 내보낼 수 없습니다. 이것은 babel에서 가져온 것입니다.

var obj = {x:1, y: 1, z: 1};
var {z, ...obj1} = obj;
var __objectWithoutProperties = function(obj, keys) {
    var target = {};
    for (var i in obj) {
        if (keys.indexOf(i) >= 0) continue;
        if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
        target[i] = obj[i];
    }
    return target;
};

var obj = {x:1, y: 1, z: 1};
var z = obj.z;
var obj1 = __objectWithoutProperties(obj, ["z"]);

_편집: 약간의 타이핑/방출 예제 추가_

Committed ES Next Fixed Suggestion

가장 유용한 댓글

나는 우리가 그것을 결국 어떻게 배송할지 확신할 수 없지만 객체 리터럴과 구조화에서 rest/spread에 대한 작업을 시작했습니다. 지금 계획은 방출을 위해 __assign 폴리필을 사용하는 것입니다.

모든 96 댓글

이것이 어떻게 하위 수준에서 그럴듯하게 방출될 수 있는지에 대한 몇 가지 예가 필요할 것입니다(범위 내에 있는 경우).

@RyanCavanaugh , 나는 약간의 방출 예제와 타이핑 아이디어를 추가했습니다.
어쨌든 jsx 기능이기 때문에 작업하고 싶습니다. 포크에 추가해야 하지만, typescript 코어에 추가하면 더 좋습니다 ^^.

최근에 이 기사 를 통해 ES7에서 이 기능을 발견했습니다. 꽤 편리합니다!

TypeScript에서 이것을 보고 싶습니다!

이에 대한 업데이트가 있습니까? React :smile과 함께 사용할 때 매우 편리할 것이기 때문에 1.6에서 이것을 보고 싶습니다.

@prabirshrestha 기록을 위해 현재 master 에 JSX에 대한 속성 스프레드 연산자가 있습니다.

@DanielRosenwass 자세히 나머지 속성 을 포함합니까 아니면 그냥 속성을 확산 합니까?

죄송합니다 @mnpenner@prabirshrestha , 예, master 의미했습니다. @RyanCavanaugh 는 이것에 대해 나보다 더 많이 알고 있지만, 나는 그것이 단지 퍼진 속성이라고 생각합니다.

JSX는 스프레드 _속성_을 지원합니다(예: <TagName {...spreadedExpr} /> . 동일한 토큰을 공유하고 대략적으로 동등한 의미를 갖는 것 외에는 ES6 스프레드 연산자와 관련이 없습니다.

저는 Redux 와 React 모두에 매우 관심이 있습니다. 이를 통해 상태 조작이 훨씬 쉬워졌습니다. 이것이 구현되는 것을 보고 싶습니다.

Rest/Spread는 현재 2단계에 대해 승인되었습니다. https://github.com/tc39/tc39-notes/blob/master/es7/2015-07/july-30.md

우리는 이 문제를 다루기 전에 제안이 3단계에 도달하기를 기다리고 싶습니다.

react 와 redux 에서 매우 유용합니다. 최대한 빨리 구현해주세요 :-)

다음은 이 문제를 해결하는 데 사용한 도우미 모듈입니다. 모든 키를 두 번 지정해야 하므로 이상적이지 않습니다. 한 번은 왼쪽에, 한 번은 오른쪽에 문자열로 지정해야 하지만 더 좋은 방법이 생각나지 않습니다. 어떤 피드백이든 환영합니다. 제가 놓친 에지 동작이 있다고 확신합니다!

https://gist.github.com/tomduncalf/fbae862b123445c117cb

이것이 당신이 패치를 받아들일 만한 것입니까? (3단계에 도달하면 병합됨). 그렇다면 지원을 위해 변경을 시작할 위치에 대한 포인터가 있습니까?

이것은 우리 팀이 타이프스크립트로 전환하는 것을 방해하는 마지막 ES7+ 기능입니다. 가능하다면 빨리 하고 싶어할 것입니다.

우리는 여기에서 PR을 고려할 것입니다. 그러나 이 기능에 대한 유형 시스템을 연결하는 것은 간단한 작업이 아닙니다. 이것을 정독하는 데 관심이 있다면 점진적으로 유지하고 구문 분석으로 시작한 다음 내보낸 다음 유형 검사를 수행합니다. 질문이 있는 경우 @sandersn 이 도와드릴 수 있습니다.

Redux와 함께 사용하는 데 관심이 있는 사람들을 위한 참고 사항입니다. 표기법이 편리하다는 데 동의합니다. 그러나 실제로 updeep 라이브러리를 활용하여 그것 없이도 잘 지내고 있습니다. 나는 그것에 대한 몇 가지 기본 입력을 만들었으며 꽤 잘 작동합니다. updeep 기반 저장소 및 작업을 구현하는 간단한 라이브러리도 있습니다. 누구든지 이것에 관심이 있다면 저에게 연락하십시오.

어쨌든 :+1: TS의 스프레드 연산자. :웃다:

@xogeny 그 라이브러리를 살펴보는 데 매우 관심이 있을 것입니다. 감사 해요

@cur3n4 이 아이디어를 가지고 노는 저장소 가 있습니다. (이 모든 것이 여전히 진화하고 있기 때문에) 상당히 변경됩니다. 나는 처음에 updeep 를 활용한 특별한 모듈을 사용하고 있었고 그 기능은 여전히 ​​라이브러리에 있습니다. 하지만 필요한 형식 제약 조건을 유지하기 어렵다는 것을 알았기 때문에 사용을 중단했습니다. Typescript에 Java의 super 일반 유형 제약 조건 , updeep (및 lodash 또는 ramda 와 같은 다른 여러 라이브러리)이 있을 수 있다고 생각합니다. 훨씬 더 많은 유형을 안전하게 만들었습니다.

하지만 오해하지 마세요. 여전히 스프레드 연산자가 정말 유용할 것이라고 생각합니다. 그것은 실제로 당신이 현재의 타입 시스템으로 어떻게 해야할지 모르는 언어로 안전하고 간결하게 표현하고 할 수 있게 해줄 것입니다. 당분간은 안전을 위해 간결함을 희생합니다( updeep 접근 방식은 간결함을 위해 안전을 희생함).

지난 몇 달 동안 Babel을 사용한 후 내 프로젝트를 TS로 변환하고 이 모든 작업을 다시 수행해야 했습니다. 이것이 구현되는 것을 보고 싶습니다!

:+1:

이것을 보고 싶습니다.

+1

기능이 있어야 합니다. 구현하십시오.

+1

+1 Object.assign + JSX 지원보다 훨씬 더 멋진 구문

+1 props를 전달하기 위한 반응 개발에 필수입니다( var { checked, ...other } = this.props; . 반응 문서 참조

반응 개발을 위해 반드시 있어야 합니다.

솔직히 말해서, 그것은 편리함이지 꼭 있어야 하는 것은 아닙니다. 제안은 TC39와 함께 2단계에 있습니다. TypeScript 팀은 3단계가 될 때까지 TypeScript에서 시작되지 않은 것을 구현하는 것을 고려하고 싶지 않다는 점을 분명히 했습니다. "+1"의 위치는 TC39입니다.

@kitsonk - react / etc와 같은 프레임워크가 문서에서 이러한 유형을 구체적으로 호출할 때 좋은 채택을 기대할 수 없습니다. 사람들은 Typescript를 사용하기 시작하고 이러한 모든 문제를 보고 Babel로 돌아갈 것입니다. 그게 내가 한 일이다.

글쎄, 우리는 더 넓은 주제에 대해 이야기하고 있다고 생각합니다. 어떤 브라우저 벤더도 3단계에 없는 것을 구현하지 않을 것입니다(개인적으로 마음에 들지 않는 한). TC39는 웹에서 일정 수준의 조직화를 시도했습니다. TypeScript는 이전에 총을 뛰어넘음으로써 엄청나게 물렸습니다(모듈과 그 이후 발생한 혼란을 살펴보세요). 나는 그들이 무엇을 언제 구현하고자 하는지에 대한 최소한의 지침과 구조를 제시하려고 노력하고 있다는 점을 존중합니다. 어떤 표준을 사용해야 하는지에 대한 다른 제안이 있습니까? 나는 "X 프레임워크가 그들의 문서에서 그것을 언급하기 때문에" 좋은 것이 될 것이라고 생각하지 않습니다.

react / etc와 같은 프레임워크는 문서에서 이러한 유형을 구체적으로 호출합니다.

제안으로만 표시한 다음 계속해서 Babel 6을 사용하도록 구성하는 방법을 알려줍니다. 나는 오히려 초안 사양에 있는 구문 기술에 의존하는 프레임워크를 비난하고 싶습니다. 개인적으로 Dojo에 있는 우리는 Object.observe 의해 화상을 입었고 Dojo의 3단계에 도달하기 전에 기술에 의존하려고 하는 것을 다시 주저합니다.

특정 경로는 TypeScript에 대해 방출 시 구문 변환을 지원하는 것 이상입니다. 따라야 하는 모든 유형 추론이 있습니다. 이해하기 위해 초안 사양을 살펴보았지만 기호는 어디로 가나요? 열거할 수 없는 속성은 어디로 가나요? 두 경우 모두 에테르 속으로 사라진다고 가정하지만 이를 위해 백그라운드에서 진행해야 하는 모든 종류의 유형 분할 및 병합이 있을 것이므로 TypeScript 팀이 "좋아, 잠시만 기다려 봅시다. TC39가 정말로 이것에 타이어를 걷어찼을 때까지 이것에".

전반적으로 나는 TS가 오늘 꽤 잘 등장했다고 생각합니다. ES2015의 일부 기능이 부족해서 답답했던 때가 있었는데(1.4~1.5 정도), 오늘 TS는 표준을 꽤 잘 따라잡았습니다.

물론 때로는 다른 언어를 부러워하는 기능이 있습니다. 예를 들어 Babel은 "실험적인" 항목을 포함하여 거의 모든 JS 제안을 제공합니다. 개인적으로 이 문제와 함수 바인딩 연산자도 기대하고 있습니다.

그러나 동시에 우리는 TS 팀이 Babel보다 호환성을 훨씬 더 중요하게 여긴다는 것을 인정해야 합니다. 그들은 릴리스 간에 코드의 의미를 변경하거나 Babel이 하는 기능을 단순히 제거하는 것을 원하지 않습니다. 일부(엔터프라이즈?) 프로젝트의 경우 중요합니다.

나는 또한 MS가 삭제될 수 있는 기능에 많은 리소스를 투자하고 싶지 않다는 것을 이해할 수 있습니다. Object.observe 실패가 떠오릅니다. 실제로, 그들은 예를 들어 윙크:에 대한 홍보를 고려할 것이라고 말했습니다

과거에는 일부 기능이 실험적 컴파일러 스위치(예: 비동기) 뒤에 일찍 추가되었습니다. 즉, 향후 릴리스에서 기능이 변경되거나 제거될 수 있음을 확인하고 선택해야 했습니다. 가장 인기 있는 요청에 대해 다시 수행할 수 있습니까?

여기에 간단한 메모가 있습니다. 우리는 주로 이전 버전과의 호환성 문제로 인해 0-1단계 제안된 ES 기능을 채택하는 데 다소 느렸습니다. 우리는 TC39 회의의 논의를 면밀히 따르고 회의에 직접 참여하거나 회의 전에 제안 준비에 참여합니다. 기능을 추가할 때 해당 기능에 의존하는 사용자에게 이것이 어떤 의미인지 알고 싶습니다.
TC39 프로세스 문서 를 보면 1단계의 기능이 "주요" 승인 후 변경 사항을 예상할 수 있습니다. 이것은 클래스, 모듈, 반복자 및 거의 모든 중요하지 않은 ES6 기능의 경우였습니다..
내 사용자 모자를 쓰고 구문에 대한 주요 변경 사항은 기계적으로 응답할 수 있는 반면 의미론에 대한 주요 변경 사항은 파악하고 수정하기가 매우 어려울 수 있습니다. 이는 이러한 기능을 사용하는 팀에 막대한 비용이 들거나 최신 버전의 도구를 채택하는 데 방해가 될 수 있습니다. 가능하면 최소화하고 싶습니다. 이것이 우리가 기능이 3단계에 도달하면 기본적으로 기능을 활성화하고 그 이전의 실험적 플래그(예: 데코레이터)에서 기능을 활성화하는 정책을 채택한 이유입니다.
그렇긴 하지만 객체 속성 스프레드 및 나머지는 로드맵 에 있으며 향후 릴리스에서 다룰 계획입니다.

아마도 babel에서와 같이 일부 타사 확장을 삽입하는 컴파일러 기능을 추가하는 것이 좋습니다.

또 다른 생각: (Babel과 함께) typescript 소스 전처리에 대한 지원은 어떻습니까?

Babel(또는 다른 라이브러리)이 객체 스프레드를 Object.assign 호출로 확장하도록 할 수 있다면 충분히 잘 작동할까요? Babel에서 구현된 다른 실험 기능에도 일반화할 수 있기를 바랍니다.

@kitsonk - 더 넓은 주제는 절대적으로 github이 더 나은 토론을 했으면 하는 바람입니다 ;). 나는 당신에 대해 상당히 동의하지 않습니다.

. TypeScript는 이전에 총을 뛰어넘음으로써 엄청나게 물렸습니다(모듈과 그 이후 발생한 혼란을 살펴보세요).

그들은 나가서 커뮤니티의 어떤 것도 사용하지 않고 .NET을 미러링하는 자체 구현을 수행했습니다. 그건 그들 자신의 잘못입니다.

구현하고자 하는 대상과 시기에 대한 지침과 구조를 설정합니다.

데코레이터(1단계), 클래스 속성(1단계) 등을 구현합니다.

나는 "X 프레임워크가 그들의 문서에서 그것을 언급하기 때문에" 좋은 것이 될 것이라고 생각하지 않습니다.

농담 맞지? react는 가장 인기 있는 프레임워크이며 당분간은 그 상태를 유지할 것으로 예상됩니다. 그 의지를 지지하지 않는 것은/입양에 정말로 상처를 입혔습니다.

TypeScript는 Babel을 따라잡을 일이 많고 다음과 같은 많은 문제가 있다고 생각합니다. 기존 앱과 함께 사용하기 시작하기가 정말 어렵습니다. babel에서 A2용 typescript로 마이그레이션하는 것은 악몽입니다!, 분리된 플러그인 부족 노드를 사용하여 작업하는 것을 매우 어렵게 만듭니다.

농담 맞지? react는 가장 인기 있는 프레임워크이며 당분간은 그 상태를 유지할 것으로 예상됩니다. 그 의지를 지지하지 않는 것은/입양에 정말로 상처를 입혔습니다.

나는 React에 대해 많은 존경심을 가지고 있지만 농담이 아닙니다. 그것은 도시의 유일한 게임이 아니며 확실히 큰 과대 광고 곡선에 있습니다. 6개월 전에는 React + Flux였습니다. 이제는 React + Redux가 오늘의 맛입니다. 1년 전, Angular와 Polymer. 2년 전에는 Backbone과 Ember였습니다. 6년 전에는 Dojo, MooTools, jQuery, gwt, ExtJS 등이 있었습니다.

여기에서 프레임워크 전쟁을 시작하지 마십시오.
{..., } 구문은 프레임워크에 관계없이 있는 그대로 매우 멋집니다.

그들은 나가서 커뮤니티의 어떤 것도 사용하지 않고 .NET을 미러링하는 자체 구현을 수행했습니다. 그건 그들 자신의 잘못입니다.

@amcdnl 정확히 무엇을 말씀하시는 건가요? 나는 당신이 .NET과 아무 관련이 없으며 TypeScript의 모듈과 관련된 주요 문제점 중 하나가 아닌 네임스페이스 문제로 모듈을 언급하고 있다고 가정할 수 있습니다.

이것이 typescript 노드 js에 포함되도록 +1은 실험적으로 지원하고 있습니다.

let typescript = { ...typescript, object_spread }; // 예, 부탁합니다.

이 부분에 움직임이 없습니다. 빨리 3단계에 도달하기를 바랍니다. 가능한 경우 VSCode에서 구문 오류 강조 표시를 종료합니다.

Salsa가 게임에 어떤 변화를 주는지 궁금합니다.

TS는 제한된 리소스, 가능한 주요 변경 사항으로부터 사용자 보호 등 불안정한 기능을 조기에 구현하기를 원하지 않는다는 것을 이해합니다.

그러나 이제 Salsa가 VS Code 기본 JS 엔진이므로 새로운 JS 구문(적어도 전체 TS 타이핑이 아닌 구문만)에 대한 압력이 증가할 것입니다. 특히 Babel의 인기를 감안할 때.

Salsa는 TS보다 더 광범위한 구문을 더 빠르게 수용할 수 있습니까?

+1

이것은 2.0이 아닌 2.1에 있습니까? :울다:
https://github.com/Microsoft/TypeScript/wiki/Roadmap#21

2.0이 이미 얼마나 큰지 생각해보면 그리 놀랍지 않습니다.

우리는 릴리스를 6-8주 간격으로 유지하려고 노력합니다. 그래서 들어갈 수 있는 것을 제한합니다. 우리는 현재 이미터 리팩토링을 수행하고 있으며 완료되면 이 기능을 추가할 수 있어야 합니다.

그래서 이게 고쳐졌나요?

...확산 속성에 대한 독립형 도우미 기능
https://github.com/Microsoft/TypeScript/releases/tag/v1.8.10

나는 여전히 "재산 구조 조정 패턴이 예상됨"을 받고 있기 때문에

정확히. 해당 수정 사항은 특히 JSX 스프레드 속성을 위한 것입니다.

const props = { foo: "bar" };
return <SomeComponent {...props} />;

React v15가 TypeScript의 JSX 컴파일러가 의존하는 문서화되지 않은 내부 기능을 제거하기 전에 이미 작동했습니다. 앗 😃

Object Spread는 다른 제안으로, 구문이 비슷하다는 것이 인정됩니다(Facebook 엔지니어가 제안한 것일 수도 있고 JSX에 해당하는 것에서 영감을 받았을 수도 있지만 확실하지는 않음).

{...props} 가 아직 작동하지 않기 때문에 TypeScript를 사용하여 이와 유사한 결과를 얻으려면 어떻게 해야 합니까?

따라서 {...props}가 아직 작동하지 않기 때문에 TypeScript를 사용하여 이와 유사한 결과를 얻으려면 어떻게 해야 합니까?

xtend : https://www.npmjs.com/package/xtend 타이핑이 좋습니다. https://github.com/typed-typings/npm-xtend (by @blakeembrey :rose:) 감사합니다. 교차로 유형으로

아니면 라이브러리를 전혀 사용하지 마십시오!

const newProps = Object.assign({} /*new object*/, props /* add all attributes of props */, {
   // add additional props
  bar: "baz"
});

약간 장황하지만 ES2015에 기본적으로 포함되어 있으므로 이미 폴리필이 있는 경우 확실합니다.

이 연산자는 프로젝트에서 typescript 대신 babel을 사용하기로 결정한 주요 이유 중 하나입니다.

개체를 변경할 수 없도록 처리하는 게임을 완전히 변경합니다.

대안으로 babel에서 할 수 있는 것처럼 TSC에 사용자 지정 변환을 연결할 수 있는 계획이 있습니까? 같은 API를 기반으로 하는 경우에도 이와 같은 문제를 해결하고 해결할 수 있습니다.

대안으로 babel에서 할 수 있는 것처럼 TSC에 사용자 지정 변환을 연결할 수 있는 계획이 있습니다.

@Niondir 네. [Transforms] 태그를 검색하면 됩니다. TypeScript 컴파일러 :rose로 적절한 async/await/generator 변환을 얻으려면 다음이 필요합니다.

조금 검색 후, 당신은 이것을 참조하고 있습니까? https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API

잘 들리네요. 해당 API의 Object Spread와 관련된 항목을 찾지 못했습니다. 아마도 Compiler API를 기반으로 이 문제를 해결하는 좋은 작은 프로젝트가 될 것입니다. :)

@Niondir 내 원래 메시지에서 더 나은 도움을 제공하지 https://github.com/Microsoft/TypeScript/issues/5595 <에 대해 이야기하고 emit 를 허용합니다. TypeScript는 코드에 대한 _semantic_ 유형의 시스템 이해가 필요하기 때문에 Babel보다 약간 더 복잡하므로 개체 확산 작업은 TypeScript 팀에서 수행해야 할 것입니다.

플러그인 기반 이미터를 사용하면 이 작업이 더 쉬워집니다. 예를 컴파일러 API를 사용합니다 (잠재적 또는 fork 플러그인 시스템까지 처음에 컴파일러는 의미 / 스캐너 로직 공개 + 이루어집니다)

이것은 다른 문제에 대한 질문일 수 있지만 "실험 허용" 옵션을 추가하고 TypeScript에서 향후 작업을 허용하도록 하는 것이 가능하지 않을까요? 예를 들어, 스프레드 연산자와 출력을 있는 그대로 허용합니다. 나중에 babel로 처리할 수 있습니다.

이것은 내가 작업하고 있는 일부 프로젝트의 필수 기능이며 이와 같은 필수 항목 없이는 마이그레이션할 수 없습니다. 내가 할 수 있다면 그것은 굉장 할 것입니다.

나는 우리가 그것을 결국 어떻게 배송할지 확신할 수 없지만 객체 리터럴과 구조화에서 rest/spread에 대한 작업을 시작했습니다. 지금 계획은 방출을 위해 __assign 폴리필을 사용하는 것입니다.

이것은 내가 지난 3개월 동안 들은 최고의 소식입니다!

불행히도 이것이 제네릭과 함께 작동하도록 하는 것은 _많은_ 작업이라는 것이 밝혀졌습니다. 다음과 같은 코드를 적절하게 지원해야 합니다.

function addId<T>(t: T): {...T, id: number} {
    return { ...t, id: 1 };
}

보시다시피 addId 는 스프레드 연산자를 포함하는 객체 유형인 새로운 유형의 유형을 반환합니다.

약간의 논의 끝에 2.1까지 미루고 다시 살펴보기로 했습니다. 우리는 지금 2.0 기능을 완료하는 데 집중해야 합니다.

제 무지를 용서해 주세요... 하지만 addId 같은 경우 T & { id: number } 를 반환할 수 있습니까? 아니면 최적의 솔루션이 되는 것을 막는 유니온 유형의 기이한 점이 있습니까?

나는 그가 T에 무엇이든 전달할 수 있기 때문에 실제로 T 를 확인해야 한다는 것을 의미한다고 생각합니다.

addId<boolean>(true);
addId<number>(5);

Babel은 이러한 진술을 조용히 무시합니다 let a = { ...true } 하지만 유효하지 않아야 한다고 생각합니다

Tid 속성이 있으면 재정의되기 때문에 T & { id: number } 가 아닙니다.

반면에 id 의 결과 유형인 교차는 Tid 유형과 number 의 교차입니다.

따라서 @sandersn 이 말하는 것은 별도의 유형 연산자가 필요하다는 것입니다.

여기서 더 나은 타이핑 솔루션을 사용하면 확실히 이점을 얻을 수 있지만 Object.assign 이미 존재하며 교집합을 출력 유형으로 순진하게 사용합니다. 정지 간격 측정으로서 Object.assign 가 하는 일을 정확히 하는 나머지 연산자를 가질 수 없는 이유는 무엇입니까?

누락된 기능에 대한 많은 우려를 완화하고 사람들이 이미 Object.assign 대신 사용하기 때문에 원치 않는 동작을 가져오지 않을 것입니다.

실제로 이것이 지원되지 않는다는 사실에 매우 놀랐습니다.

우리가 이것을 얻는 즉시 더 즐겁습니다. 반응과 함께 잘 작동합니다!

타이핑 안 했어도 기쁠 텐데

@2426021684 합리적으로 들릴지 모르지만 그 의미를 고려하십시오. 입력되지 않은 경우, 즉 any 로 입력된 경우 구문을 사용하면 any 가 표현식의 잎으로 스며들게 됩니다.

@aluanhaddad Object.assign같을 것입니다. 이는 선택의 여지가 없기 때문에 모두가 사용해야 하는 해결 방법입니다(위의 JabX 게시물 참조).

가까운 시일 내에 @JabX 의 제안을 구현하는 것을 고려하십시오. 이 제안은 이름을 제외하고는 모두 3단계이며 표준의 일부가 될 _확실히_이며 매우 명확하고 간단한 의미를 가지고 있습니다. 속성 스프레드에 대한 구문 지원 + Object.assign 의 순진한 입력은 "올바른" 구현을 기다리는 동안 매우 유용한 임시방편이 될 것입니다. 완벽함을 선의 적이 되게 하지 마십시오.

Rest 속성은 https://facebook.github.io/react/warnings/unknown-prop.html에서 볼 수 있듯이 React 15.2에서 매우 중요합니다.

const divProps = Object.assign({}, props)
delete divProps.layout

특히 구성 요소의 소품 수가 더 많은 경우 매우 추악합니다.

더 이상 기다릴 수 없는 사람들을 위한 해결 방법은 다음과 같습니다.

function steal(result: any, data: any): any {
    for (var key in data) {
        if (value.hasOwnProperty(key)) {
            result[key] = data[key];
        }
    }
    return result;
}

export class SameAs<a> {
    constructor(public result: a) { }
    public and<b>(value: b): SameAs<a & b> {
        return new SameAs<a & b>(steal(this.result, value));
    }
}
export function sameAs<a>(value: a): SameAs<a> {
    return new SameAs(steal({}, value));
}

// example of use:

const mixture = sameAs(one).and(anotherOne).and(yetAnotherOne).result; // <-- ta-da!

이 게시물을 무시하십시오. 더 나은 구현을 위해 아래를 참조하십시오.

다음은 가난한 (typescript) 코더의 구조 분해 작업에 대해 생각해 낸 것입니다.

declare interface ObjectConstructor {
  destruct<T extends Object>(data: T, props: any): T;
  destruct<T extends Object>(data: T, ...propNames: string[]): T;
}

function destruct<T extends Object>(data: T, ...removals: string[]) {
  const rest = <T>{};

  const keys = removals.length === 1 && typeof removals[0] === 'object' ?
    Object.getOwnPropertyNames(removals[0]) :
    <string[]>removals;

  Object
    .getOwnPropertyNames(data)
    .filter(x => keys.indexOf(x) < 0)
    .forEach(x => {
      (<any>rest)[x] = (<any>data)[x];
    });

  return rest;
}

Object.destruct = destruct;

// Usage example:

const srcObj = { A: 'a', B: 'b', C: 'c' };
// destruct using an object template
const onlyC = Object.destruct(srcObj, { A: null, B: null });
// destruct using property names
const onlyA = Object.destruct(srcObj, 'B', 'C');

개체 레이아웃을 사용하는 것의 명백한 이점은 레이아웃을 입력할 수 있고 어떤 것을 리팩토링하는 경우 최소한 유형 충돌이 발생할 수 있다는 것입니다.

업데이트(이것도 무시하십시오. 더 나은 방법은 아래 참조)

나는 이것을 재작업했고(실제 환경에서 그것을 어지럽힌 후) 함수로 작업하기 훨씬 더 쉬운 몇 가지를 생각해 냈습니다.

function deconstruct<TResult, TData>(
  result: TResult,
  data: TData,
  onHit: (result: TResult, data: TData, x: string) => void,
  onMiss: (result: TResult, data: TData, x: string) => void,
  propNames: string[]
  ) {

  Object
    .getOwnPropertyNames(data)
    .forEach(x => {
      if (propNames.indexOf(x) < 0) {
        if (onMiss != null) {
          onMiss(result, data, x);
        }
      }
      else {
        if (onHit != null) {
          onHit(result, data, x);
        }
      }
    });

  return result;
}

// shallow clone data and create a destructuring array of objects
// i.e., const [ myProps, rest] = destruct(obj, 'propA', 'propB');
function destruct<T>(data: T, ...propNames: string[]) {
  return deconstruct(
    [ <T>{}, <T>{} ],
    data,
    (r, d, x) => (<any>r[0])[x] = (<any>d)[x],
    (r, d, x) => (<any>r[1])[x] = (<any>d)[x],
    propNames
  );
}

// shallow clone data and create a destructuring array of properties
// i.e., const [ propA, propB, rest] = destructProps(obj, 'propA', 'propB');
function destructProps(data: any, ...propNames: string[]) {
  return deconstruct(
    [ <any>{} ],
    data,
    (r, d, x) => r.splice(r.length - 1, 0, d[x]),
    (r, d, x) => r[r.length - 1][x] = d[x],
    propNames
  );
}

// shallow clone data and remove provided props
// i.e., const excluded = omit(obj, 'excludeA', 'excludeB');
function omit<T>(data: T, ...propNames: string[]) {
  return deconstruct(
    <T>{},
    data,
    null,
    (r, d, x) => (<any>r)[x] = (<any>d)[x],
    propNames
  );
}

이러한 기능을 입력하면 작업이 훨씬 쉬워집니다. 저는 특히 React에서 이것들을 사용하고 있으므로 알려진 props에 강력한 타이핑을 하는 것이 매우 편리합니다. 반응에 특히 편리한 이러한 기능을 사용하는 추가 코드가 있습니다.

const [ props, restProps ] = destruct(omit(this.props, 'key', 'ref'), 'id', 'text');

이 경우 propsthis.props 와 같이 입력되지만 라인 아래로 전송하기 위한 소품(현재 restProps )을 포함하지 않습니다.

IMO, 이 문제에 대한 유형 안전하지 않은 해결 방법을 게시하여 얻을 수 있는 것은 많지 않습니다.

동의합니다. 저는 지금 더 유형이 안전한 버전을 작업 중입니다.

이것에 대한 또 다른 찌르기:

기본 개체 확장:

declare interface ObjectConstructor {
    rest<TData, TProps>(data: TData, propsCreator: (x: TData) => TProps, ...omits: string[]): { rest: TData, props: TProps };
}

function rest<TData, TProps>(data: TData, propsCreator: (x: TData) => TProps, ...omits: string[]) {
  const rest = <TData>{};
  const props = <TProps>propsCreator.apply(this, [ data ]);

  Object
    .getOwnPropertyNames(data)
    .filter(x => props.hasOwnProperty(x) === false && omits.indexOf(x) < 0)
    .forEach(x => {
      (<any>rest)[x] = (<any>data)[x];
    });

  return {
    rest,
    props,
  };
}

Object.rest = rest;

React 특정 확장:

declare module React {
  interface Component<P, S> {
    restProps<T>(propsCreator: (x: P) => T, ...omits: string[]): { rest: P, props: T };
  }
}

function restProps<P, S, T>(propsCreator: (x: P) => T, ...omits: string[]) {
  return Object.rest((<React.Component<P, S>>this).props, propsCreator, ...omits.concat('key', 'ref'));
}

React.Component.prototype.restProps = restProps;

일부 샘플 사용법:

const src = { A: 'a', B: 'b', C: 'c' };
const { rest, props } = Object.rest(src, x => {
    const props = { A, C } = x;
  return { A, C };
});

그리고 반응 확장을 사용하는 샘플:

const { rest, props } = this.restProps(x => {
  const { header, footer } = x;
  return { header, footer };
});

모든 입력은 보존되어야 합니다. 나를 괴롭히는 유일한 부분은 복제가 필요하기 때문에 소품 제작자입니다. 나는 그것을 해킹할 수 있고 구조화되지 않은 개체가 _a 있다고 가정할 수 있다고 생각하지만 그것은 _위험한_ 것 같습니다...
_ 참고 _: _ax같으므로 실행 가능한 해킹도 아닙니다.

다음은 가지고 놀 수 있는 Fiddle 입니다.

필요에 따라 출력 이름을 바꿀 수 있으므로 배열을 반환하는 것이 더 합리적일 수 있다고 생각합니다.

긁으면 소품에 대한 적절한 입력을 방지할 수 있습니다.

여기 대부분의 사람들은 이것을 반응과 함께 사용하기를 원하기 때문에 3단계에 도달할 때까지 *.tsx 파일에 대해서만 이것을 구현하지 않는 이유는 무엇입니까?

Redux 리듀서는 *.tsx 파일로도 작성할 수 있습니다.오브제 typecasting 인스턴스는 유형 으로

이것은 반응뿐만 아니라 예를 들어 redux 리듀서에서도 매우 유용합니다.

나는 이것에 대한 태그와 누락된 이정표가 약간 구식이라고 생각합니다. 이것은 TypeScript 2.1용으로 커밋 되고 작업 중이기 때문입니다(#10727). 그러므로 더 이상 그 가치를 논할 필요가 없습니다.

핑 @mhegazy

태그를 업데이트했습니다. 이것이 아직 구현되지 않은 이유는 값이 아니라 형식 시스템 구현의 복잡성 때문이라는 점을 분명히 해야 합니다. 변환 자체는 다소 간단합니다. 즉 {...x} 에서 Object.assign({}, x) 로의 변환입니다. 문제는 이러한 유형이 사전 테스트되는 방식과 작동 방식입니다. 예를 들어 제네릭 유형 매개변수 T 경우 {...T} 할당 가능한 T , {x: number, ...T} , T 에 메서드가 있는 경우, etc.. https://github.com/Microsoft/TypeScript/issues/10727 은 필요한 유형 시스템 변경 사항에 대한 자세한 설명을 제공합니다.

이 기능을 이상적으로 처리하는 데 필요한 유형 시스템 확장이 사소한 일이 아니라는 점에 대해 전적으로 감사하며 열성적으로 해결되는 것을 보는 것은 좋습니다! 다시 말하지만,

속성 스프레드에 대한 구문 지원 + Object.assign의 순진한 타이핑을 배치하는 것은 "올바른" 구현을 기다리는 동안 매우 유용한 임시방편이 될 것입니다. 완벽함을 선의 적이 되게 하지 마십시오.

제안이 3단계에 도달한 것 같습니다: https://github.com/tc39/proposals

@ddaghan tsx를 사용한 예제가 작동하지 않습니다.

이 기능에 대한 기간이 있습니까?

@SpyMaster356 나는 이것을 잠시 동안 @sandersn 은 지난 몇 주 동안 (최소한) 이것에 대해

여기(https://github.com/Microsoft/TypeScript/pull/12028) 및 여기(https://github.com/Microsoft/TypeScript/pull/11150)를 따라할 수 있습니다.

누군가는 로드맵을 업데이트해야 합니다

이 기능을 사용하면 알 수 없는 소품을 할당할 수 있는 것 같습니다.

interface State {
  a: string;
  b: number;
}

let state: State = { a: "a", b: 0 };

state = {...state, x: "x"}; // No error

xState 의 알려진 속성이 아니라는 오류를 예상했습니다. 이것이 기능이 작동하는 방식이 아닙니까?

예를 들어, 이 PR 이전의 현재 해결 방법은 다음과 같습니다.

state = update(state, { x: "x" }); // Error: Property 'x' is missing in type 'State'.

function update<S extends C, C>(state: S, changes: C): S {
  return Object.assign({}, state, changes);
}

객체 확산/휴식으로 이것을 달성할 수 있습니까?

ES 제안에 따라 Object Rest and Spread 는 Object.assign 와 유사하게 작동합니다. 속성의 마지막 언급은 "승리"합니다. 오류가 보고되지 않습니다. 당신이 가진 예에서 {...state, x:"X"}{ a: string, b:number, x:string } . 이 유형은 State 에 할당할 수 있으므로 할당이 작동합니다. 이것은 let state: State = { a: "a", b:0, x: "X" }; 도 허용된다는 것과 같습니다.

그러나 그것이 내가 혼란스러워하는 것입니다. let state: State = { a: "a", b:0, x: "X" } 는 오류 Object literal may only specify known properties, and 'x' does not exist in type 'State' 이는 내가 원하는 것입니다... 스프레드가 포함된 개체 리터럴에서 나올 때 유효한 할당인 이유는 무엇입니까?

죄송합니다.. 객체 리터럴은 특별한 경우입니다. 내 예는 틀렸다. 다음은 더 나은 예입니다.

let obj = { a: "a", b:0, x: "X" };
let state: State = obj; // OK

여기서 문제는 다소 주관적인 경우입니다. 컴파일러가 let state:State = { a: "a", b:0, x: "X" } 볼 때 x 는 오타, 리팩토링 후 생략된 오래된 속성 또는 선택적 속성의 유형일 가능성이 있습니다. 오류.

그러나 개체를 퍼뜨리는 경우 let myConfig : State= { a: 1, ...myOtherBigConfigBag} , myOtherBigConfigBag 신경 쓰지 않는 속성이 몇 개 있는 경우 ab , 여기에 오류가 발생하면 이 두 인터페이스를 동기화 상태로 유지하거나 이러한 오류를 없애기 위해 캐스트해야 합니다.

말했다. 우리는 이 결정을 재고해야 합니다. 이를 추적하기 위해 https://github.com/Microsoft/TypeScript/issues/12717 을 제출했습니다.

내가 참조. #12717에 있는 당신의 아이디어가 마음에 듭니다. 바로 그것이 내가 생각했던 것입니다. 나는 실제로 확산 소품에 대해서도 그러한 동작을 원하지만 매우 주관적이고 일부 일반적인 JS 사용 사례에서는 성가실 수 있다는 점을 알 수 있습니다.

@aaronbeall 동의합니다. 일반적인 JS 사용 사례에서는 성

안녕하세요 여러분, 훌륭한 출시를 축하합니다! 이제 휴식을 취해야 할 때입니다... 헛소리를 하자면 휴식 연산자에 문제가 있습니다. :)

React를 사용하면 일반적으로 다음과 같은 구성 요소가 있습니다.

export interface MyLinkProps extends React.HTMLAttributes {
    myUrl: string
}

class MyLink{

    render(){
      const {myUrl, ...attrs } = this.props;
     return <a href={calculate(myUrl)} ...attrs>Click here</a>;
   }
}

문제는 attrs 위로 마우스를 가져가면 React.HtmlAttributes 대신 모든 속성(수백 개) 목록이 표시된다는 것입니다.

typescript가 구조적으로 유형이 지정된다는 것을 알고 있지만 나머지 변수에 명시적 유형을 할당할 수 있습니까?

몇 가지 대안:

    const {myUrl, ...attrs as React.HtmlAttributes } = this.props; //Is not really a casting

    const {myUrl, ...attrs : React.HtmlAttributes } = this.props; //conflicts with ES6?

    const attrs : React.HTMLAttributes; 
    const { myUrl, ...attrs } = this.props;  //re-declare the variable

@bondz 글쎄, 내 프로젝트에서 100% 사용하는 것은 사실이 아닙니다. :) 그러나 다른 프로젝트에서는 매우 성가실 수 있습니다. 제 경우에는 Redux와 React를 사용하고 불변 상태를 많이 사용하고 있습니다. 즉, 상태 개체를 업데이트하거나 생성하려면 모든 소품을 새 개체 리터럴에 복사해야 합니다... 모든 경우에 100% 유형 안전성을 원합니다. 대상 상태 인터페이스에 올바른 데이터를 복사하려고 합니다. 현재 나는 이 안전을 보장하기 위해 함수를 사용하지만 더 깨끗하고(가독성, 표현력이 뛰어난 표준 구문) 개체 확산을 사용하는 것을 선호합니다. 그러나 다른 사람의 프로젝트에서는 유형이 지정되지 않거나 느슨한 개체를 많이 사용하기 때문에 다른 동작을 원할 수 있습니다. 구조이므로 매우 주관적입니다. #12717 제안이 좋은 중간 지점이라고 생각합니다(그리고 기존 객체 리터럴 유형 안전성과 더 일치함).

https://github.com/Microsoft/TypeScript/issues/2103#issuecomment -145688774
우리는 이 문제를 다루기 전에 제안이 3단계에 도달하기를 기다리고 싶습니다.

이미 상태 3인 것 같은데, 이를 지원할 계획이 있습니까?

Btw, 우리는 아직 TS가 아닌 ES 개발을 위해 주로 VSCode를 사용합니다. :)

@evisong 이 기능은 제공되었으며 최신 버전의 vsCode에서 이미 사용할 수 있습니다. vsCode를 버전 1.8로 업데이트하십시오.

이 페이지가 도움이 되었나요?
0 / 5 - 0 등급