GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing github.com — Generic rest of intersection should be assignable to its type parameter constituents · Issue #28636 · microsoft/TypeScript Open Labels In DiscussionNot yet reached consensusNot yet reached consensusSuggestionAn idea for TypeScriptAn idea for TypeScript DescriptionSearch Termsgeneric rest intersection type parameter SuggestionThe rest of an intersection containing type parameters and object types should be assignable to the type parameters if the rest removed all the properties from the object types. For example: function ripoff<T>(augmented: T & { a }): T { const { a, ...original } = augmented; return original; } This is technically not safe — the instantiation of the type parameters could overlap with the object types — but it is how higher-order spread currently behaves. I believe the most common use of rest is with disjoint types. (Spread is similar, but identical types is the most common use there.) One way to allow this is to create a new assignability rule: Pick<T & U & ... & { a } & { b } & ..., Exclude<keyof T & U & ..., 'a' | 'b' | ...>> ⟹ T & U & ... In prose, the rule is that the pick of an intersection that consists of only type parameters and object types is assignable to the intersection of the type parameters if the second argument is an Exclude, and the Exclude's first argument is Another optional is a simpler rule, where the pick of any intersection with a type parameter T is assignable to T: Pick<T & ..., Exclude<keyof T & ..., K>> ⟹ T Note that these rules don't cover what to do with constrained type parameters. The second rule is inaccurate enough already that it probably doesn't matter, but the first rule should probably have an additional restriction on Exclude's second argument. Use CasesReact HOCs basically all do this. ExamplesFrom this comment: import React, { Component } from 'react' import { Counter } from './counter-render-prop' import { Subtract } from '../types' type ExtractFuncArguments<T> = T extends (...args: infer A) => any ? A : never; // get props that Counter injects via children as a function type InjectedProps = ExtractFuncArguments<Counter['props']['children']>[0]; // withCounter will enhance returned component by ExtendedProps type ExtendedProps = { maxCount?: number }; // P is constrained to InjectedProps as we wanna make sure that wrapped component // implements this props API const withCounter = <P extends InjectedProps>(Cmp: React.ComponentType<P>) => { class WithCounter extends Component< // enhanced component will not include InjectedProps anymore as they are injected within render of this HoC and API surface is gonna be extended by ExtendedProps Subtract<P, InjectedProps> & ExtendedProps > { static displayName = `WithCounter(${Cmp.name})`; render() { const { maxCount, ...passThroughProps } = this.props; return ( // we use Counter which has children as a function API for injecting props <Counter> {(injectedProps) => maxCount && injectedProps.count >= maxCount ? ( <p className="alert alert-danger"> You've reached maximum count! GO HOME {maxCount} </p> ) : ( // here cast to as P is needed otherwise compile error will occur <Cmp {...injectedProps as P} {...passThroughProps} /> ) } </Counter> ); } } return WithCounter; }; // CounterWannabe implement InjectedProps on it's props class CounterWannabe extends Component< InjectedProps & { colorType?: 'primary' | 'secondary' | 'success' } > { render() { const { count, inc, colorType } = this.props; const cssClass = `alert alert-${colorType}`; return ( <div style={{ cursor: 'pointer' }} className={cssClass} onClick={inc}> {count} </div> ); } } // if CounterWannabe would not implement InjectedProps this line would get compile error const ExtendedComponent = withCounter(CounterWannabe); ChecklistMy suggestion meets these guidelines:
Reacted by Martin Hochel, SlurpTheo, Alexander Trauzzi, PsixokoT, Denis Rul and Daniil Lipatkin Activity
MetadataMetadataAssigneesLabelsIn DiscussionNot yet reached consensusNot yet reached consensusSuggestionAn idea for TypeScriptAn idea for TypeScript TypeProjectsMilestoneRelationshipsDevelopmentIssue actions |
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |