æªå®çŸ©ã§ãã£ãŠã¯ãªããªãããŒã«å¯ŸããŠundefined
ãè¿ããšãReactã«ãã£ãŠããŒãæªå®çŸ©ã«èšå®ãããããã Pick
ãsetState
ã®ã¿ã€ãã«äœ¿çšãããããšãç解ããŠããŸãã
ãã ãã Pick
ãšãä»ã®åé¡ãçºçããŸãã 1ã€ã¯ãã³ã³ãã€ã©ãµãŒãã¹ã®ãªãŒãã³ã³ããªãŒãã¯ããªãŒãã³ã³ããªãŒãã«Pick
ã®çµæã䜿çšããããã圹ã«ç«ããªããªããŸããã³ã³ããªãŒãããªã¯ãšã¹ããããšã Pick
ã®çµæã«ã¯ãŸã ããŒãå«ãŸããŠããŸããããªãŒãã³ã³ããªãŒããããã ããããã³ãŒã«ããã¯åŒæ°ã䜿çšããŠsetState
ãæžã蟌ãå Žåãåé¡ã¯ç¹ã«ã²ã©ããã®ã§ãã
return
ã¹ããŒãã¡ã³ãããååŸãããŸãã returnã¹ããŒãã¡ã³ãã§ç¹å®ã®ããŒãè¿ããªãå Žåã¯ãããŒã®ãªã¹ããnever
ã«ãªã»ããããã«ãåŒæ°ã§ãã®ããŒãèªã¿åãããšãã§ããŸããã è€æ°ã®returnã¹ããŒãã¡ã³ããç°ãªãããŒãè¿ãå Žåãç¹ã«ã©ããã«æªå®çŸ©ã®returnãããå ŽåïŒ if (state.busy) { return }
ïŒãèšè¿°ãé£ããå ŽåããããŸããthis.setState(input => ({ ...input, count: +input.count + 1 }))
ïŒã§å
¥åã䜿çšããããšã§åé¿ã§ããŸããã setState
ãã³ãŒã«ããã¯ã®æ»ãå€ãæž¡ããããããã¯åé·ã§ãããç¹ã«å€§èŠæš¡ãªç¶æ
ã§ã¯æé©åã解é€ãããŸãã Object.assign
ãPick
ã¯ããŒã«never
ãéžæããé¢æ°ã¯_anything_ãè¿ãããšãã§ããŸãã æ¢åã®ããŒãšäžèŽããããŒã§ãããå€ãšããŠany
ãå¹æçã«èš±å¯ããŸã-ãããé©åããªãå Žåãããã¯Pick
edã§ã¯ãªãã {}
è¶
éããããã£ãšããŠæ±ãããŸãnever
ããžã§ããªãã¯åŒæ°ãšããŠéžæãããå Žåãäžèšã®çç±ã®ããããã«ãããã³ãŒã«ããã¯åŒæ°ã¯å®éã«ã¯setState
ã®ãªããžã§ã¯ã圢åŒãžã®åŒæ°ãšããŠæ±ãããå¯èœæ§ããããŸãã ããã«ãããã³ãŒã«ããã¯ã®åŒæ°ã¯{}
ã§ã¯ãªãany
ãšå
¥åãããŸãã ãªããããæé»ã®ãšã©ãŒã§ã¯ãªãã®ãããããŸãããinterface State {
count: string // (for demonstration purposes)
}
class Counter extends React.Component<{}, State> {
readonly state: Readonly<State> = {
count: '0'
}
render () {
return React.createElement('span', { onClick: this.clicked }, this.state.count)
}
private readonly clicked = () => {
this.setState(input => ({
count: +input.count + 1 // not a type error
// the setState<never>(input: Pick<State, never>) overload is being used
}))
}
}
èŠçŽãããšã Pick
䜿çšãããšãå€å°ã®äžäŸ¿ã¯ãããŸããã setState
ã®éã³ãŒã«ããã¯åœ¢åŒã§ã¿ã€ããšã©ãŒããã£ããããã®ã«åœ¹ç«ã¡ãŸãããã³ãŒã«ããã¯åœ¢åŒã§ã¯å®å
šã«éå¹æã§ãã ããã§ã¯ã undefined
ãçŠæ¢ãããšããæå³ãããã¿ã¹ã¯ãå®è¡ããªãã ãã§ãªããã³ãŒã«ããã¯ã®å
¥åãŸãã¯åºåã§ã®åãã§ãã¯ããŸã£ããç¡å¹ã«ããŸãã
ãããããå°ãªããšãã³ãŒã«ããã¯ãã©ãŒã ã§ã¯ã Partial
ã«å€æŽããå¿
èŠãããã以åã®å®çŸ©ã§è¡ãããããã«ããŠãŒã¶ãŒãundefined
å€ãè¿ããªãããšãç¥ã£ãŠããããšãé¡ã£ãŠããŸãã
ãæèŠãããã ãããããšãããããŸãã ããã¯ããªããæèµ·ããéåžžã«èå³æ·±ãäºäŸã§ãã
æèŠãè¿°ã¹ãåã«ããã®åœ±é¿ã«ã€ããŠå°ãèããå¿ èŠããããŸãã
ããæç¹ã§ã @ ahejlsbergã¯ãªãã·ã§ã³ã| undefined
ãšã¯ç°ãªãæ¹æ³ã§æ±ããããšèããŠããŸããã ãããã£ãŠã foo?: string
ã¯ãfooãèšå®ãããŠããªãããæååã§ããããšãæå³ããŸãã
ããããã£å€ãèªã¿åãå Žåããã®å·®ã¯99.9ïŒ
ã®ç¢ºçã§ç¡é¢ä¿ã§ãããæžã蟌ã¿ã®å Žåãç¹ã«Partial<>
å Žåãåºå¥ã¯éåžžã«éèŠã§ãã
æ®å¿µãªãããããã¯é倧ãªèšèªå€æŽã§ããããã3.0ãåŸ ã€ãããã©ã°ã®åŸãã«çœ®ãå¿ èŠããããŸãã
ç§ãã¡ãå€æŽãèšã£ããšãããã Partial<>
ã¯ããã®äœ¿çšãäžç®ã§æåŠãããšããç§ã®çŸåšã®æ矩ã®ä»£ããã«ãå€ãã®äººã«ãšã£ãŠéåžžã«åœ¹ç«ã€ããã«ãªããŸãã
@ahejlsbergããªããå¿ãã人ã ãšç¥ã£ãŠããŸãããå®è£ ããã®ã¯ã©ãã»ã©é£ããã§ããããïŒ undefinedãæé»ã®å²ãåœãŠå¯èœãªå€ã§ã¯ãªãããã«ïŒ
ããŠãä»æãã°ããæéããããŠåé¡ã«ã€ããŠèããåŸãããªããææ¡ããåé¡ã«å¯Ÿããããã€ãã®ã解決çãããããããããã«ããªãéãå¯äœçšããããŸãã
interface State { foo?: string }
ïŒãæååãæå³ããããèšå®ãããŠããªããã®ã«å€æŽããŸããäŸïŒ
interface State {
foo: string;
bar: string;
}
const bleh: Partial<State> = { foo: "hi" }; // OKAY
const bleh: Partial<State> = { foo: undefined; } // BREAK
ããã«ãããæè¡çã«åé¡ã解決ããã Partial<>
ã䜿çšã§ããããã«ãªããŸããã98ïŒ
ã®ã±ãŒã¹ã¯ããå°é£ã«ãªããŸãã ããã¯äžçãå£ãã®ã§ã3.xãŸã§å®éã«è¡ãããšã¯ã§ããŸãããäžè¬ã«ãæªèšå®ãšæªå®çŸ©ã®åºå¥ãå®éã«æ°ã«ããã©ã€ãã©ãª/ãŠãŒã¹ã±ãŒã¹ã¯ã»ãšãã©ãããŸããã
äŸïŒ
interface State {
foo: string;
bar: string;
}
setState(prevState => {foo: "hi"}); // OKAY
setState(prevState => {foo: undefined}); // OKAY BUT BAD!
äŸïŒ
interface State {
foo: string;
bar: string;
}
// The following errors out because {foo: ""} can't be assigned to Pick<State, "foo" | "bar">
// Same with {bar: "" }
setState((prevState) => {
if (randomThing) {
return { foo: "" };
}
return { bar: "" };
});
// A work around for the few places where people need this type of thing, which works
setState((prevState) => {
if (randomThing) {
return { foo: "" } as State
}
return { bar: "" } as State
});
// This is fine because the following is still an error
const a = {oops: ""} as State
çŸåšãè€æ°ã®ãªã¿ãŒã³ãã¹ãããå Žåãã³ã³ãã€ã©ã¯ãã¹ãŠã®æœåšçãªããŒã1ã€ã®å·šå€§ãªPick<State, "foo" | "bar">
ãŸãšããŸãã
ãã ããäžäœäºææ§ã®ããå€æŽã¯ã Pick<State, ("foo") | ("bar")>
ãŸãã¯ããè€éãªå ŽåïŒ Pick<State, ("foo" | "bar") | ("baz")>
ããã«ããªãã©ã«ãã°ã«ãŒãåã§ããããã«ããããšã§ãã
芪ã®æ¬ åŠã¯ãæ¢åã®æ©èœã§ããå€ã®åäžã®ã»ããã瀺åããŠããŸãã
{foo: number}
ãPick<State, ("foo") | ("bar")>
ã«ãã£ã¹ãããããšãããšãæåããå¯èœæ§ããããŸãã {bar: number}
ãšåãã§ãã
Pick<State, ("foo") | ("bar")>
ã¯ã Partial<State>
ããã³{foo: number} | {bar: number}
ããã£ã¹ãã§ããŸãã
ïŒ1ïŒãšïŒ2ïŒã¯å®è¡ã§ããŸããã 1ã€ã¯ãäœããã£ãŠãã»ãŒãã¹ãŠã®äººã«è€éããããããããã1ã€ã¯ãã³ã³ãã€ã«ãããæããã«æ£ãããªãã³ãŒããäœæããã®ã«åœ¹ç«ã¡ãŸãã
ïŒ3ïŒã¯ä»æ¥å®å
šã«äœ¿çšå¯èœã§ããã setState
ã®é¢æ°ã«æœåšçãªæ»ãå€ãšããŠ| S
ãè¿œå ããçç±ãæãåºããŸããããä»ã®çç±ãæšæž¬ããããšã¯ã§ããŸããã
ïŒ4ïŒã¯ïŒ3ïŒã®åé¿çãåãé€ãããšãã§ããŸãããTypeScriptéçºè 次第ã§ããã@ ahejlsbergã«ååãªé¢å¿ãæã£ãŠããããšãé ããæ©ãããããèŠãããšãã§ãããããããŸããã
ããã«ãããã¿ã€ããå€æŽããå Žåããããä»æ¥ã®ã¿ã€ãã®æ¹ãæ£ãããšæããŸãã
ãäœãããªããã¢ãããŒãã®åé¡ã¯ãå®éã«å®éã®åãšã©ãŒãçºçããå Žåã«ãã³ã³ãã€ã©ãŒãèšè¿°ãããšããã«åäœããªãããšã§ãã ããšãã°ãäŸãå€æŽããŠãå€ã空ã®æååã§ã¯ãªã0
ã«èšå®ããå ŽåïŒ
interface State {
foo: string;
bar: string;
}
// The following does not error at all because the compiler picks `Pick<State, never>`
// The function overload of `setState` is not used -- the object overload is, and it
// accepts the function as it is accepting anything (`{}`).
setState((prevState) => {
if (randomThing) {
return { foo: 0 };
}
return { bar: 0 };
});
ä»èŠããŸãã ãµãã ãã«æ»ãã ããã«å¯Ÿããè³¢ã解決çãäœæã§ãããã©ããã確èªããŸãã æãã€ããªãå Žåã¯ãææ¡ããPartial<>
ãœãªã¥ãŒã·ã§ã³ãè©äŸ¡ããå¿
èŠããããŸãã èæ
®ãã¹ãéèŠãªããšã¯ãå€ã®äºæããªãundefined
ããäºæããªãééã£ãã¿ã€ããããäžè¬ç/ç
©ããããã®ã«ãªããã©ããã§ãã
æ確ã«ããããã«ãããã«ã¯2ã€ã®ãªãŒããŒããŒãããããŸã...
setState<K extends keyof S>(f: (prevState: Readonly<S>, props: P) => Pick<S, K>, callback?: () => any): void;
setState<K extends keyof S>(state: Pick<S, K>, callback?: () => any): void;
èšå®ã®ããããããŸãã¯ãããã®äž¡æ¹ã®Partial<S>
ã®ä»£ããã«Pick<S, K>
ããªãã®åé¡ã解決ããdoesntã®ã ããã§ããªããžã§ã¯ãããŒãžã§ã³ã«ããããã¹ã«ãŒããŸãããäœããã®çç±ã§ééã£ãã¿ã€ããåãå
¥ããŸãã
`` `ts
ã€ã³ã¿ãŒãã§ã€ã¹ã®ç¶æ
{
ããŒïŒæåå;
fooïŒçªå·;
}
ã¯ã©ã¹Fooã¯React.Component <{}ãState> {ãæ¡åŒµããŸã
public blahïŒïŒ{
this.setStateïŒïŒprevStateïŒ=>ïŒ{barïŒ1}ïŒïŒ; //ãšã©ãŒã¯ãããŸããïŒ/
}
} `` `
extends object
ã䜿çšããŠãé¢æ°ã匷å¶çã«æåŠããããšã¯ã§ããŸããïŒ
å¶çŽïŒ
éã2017幎7æ28æ¥ã«0:00ãšãªãã¯ã»ã¢ã³ããŒãœã³[email protected]ã¯æžããŸããïŒ
æ確ã«ããããã«ãããã«ã¯2ã€ã®ãªãŒããŒããŒãããããŸã...
setState
ïŒfïŒïŒprevStateïŒèªã¿åãå°çš ãå°éå ·ïŒPïŒ=>ããã¯ãã³ãŒã«ããã¯ïŒïŒïŒïŒ=>ä»»æïŒïŒvoid; setStateïŒç¶æ ïŒããã¯ãã³ãŒã«ããã¯ïŒïŒïŒïŒ=>ä»»æïŒïŒvoid;ãããã®ãããããŸãã¯äž¡æ¹
ãPickã§ã¯ãªãPartialããã¯ãŸã ãªããžã§ã¯ãããŒãžã§ã³ã«ããããã¹ã«ãŒããŸããäœããã®çç±ã§ééã£ãã¿ã€ããåãå ¥ããŸãïŒã€ã³ã¿ãŒãã§ã€ã¹ã®ç¶æ {
ããŒïŒæåå;
fooïŒçªå·;
}
ã¯ã©ã¹Fooã¯React.Component <{}ãState> {ãæ¡åŒµããŸã
public blahïŒïŒ{
this.setStateïŒïŒprevStateïŒ=>ïŒ{barïŒ1}ïŒïŒ; //ãšã©ãŒã¯ãããŸããïŒ/
}
} `` `â
ã¹ã¬ãããäœæããããããããåãåã£ãŠããŸãã
ãã®ã¡ãŒã«ã«çŽæ¥è¿ä¿¡ããGitHubã§è¡šç€ºããŠãã ãã
https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18365#issuecomment-318388471 ã
ãŸãã¯ã¹ã¬ããããã¥ãŒãããŸã
https://github.com/notifications/unsubscribe-auth/AAEdfeEJ_Ejfana14fRII1OZuS7qTuyuks5sSKX3gaJpZM4OiDrc
ã
ãã£ãŠã¿ãŸããã é¢æ°ã¯ãªããžã§ã¯ãã§ãã
ãšãªãã¯Lã¢ã³ããŒãœã³
ç§ã®iPhoneããéä¿¡ããã
ç§ã¯ããã«é¢é£ããåé¡ãå ±åããããã«æ¥ãŸãããããã¯ãç¶æ ã¿ã€ãã®ãªãã¡ã¯ã¿ãªã³ã°ããã®å€æŽã§å£ããŠãããšããããšã§ãã
ããšãã°ã httpsïŒ//github.com/tomduncalf/react-types-issue/blob/master/Test.tsxãåç
§ããŠsomething
ããªãã¡ã¯ã¿ãªã³ã°/ååå€æŽããå ŽåïŒhttps://github.com/tomduncalf/react-types-issue/blob/master/Test.tsx#L6ïŒããã®è¡ãšhttps://github.com/tomduncalf/react-types-issue/ãæŽæ°ãhttpsïŒ//github.com/tomduncalf/react-types-issue/blob/master/Test.tsxã®setState
åŒã³åºãã§ããã䜿çšã§ããŸããã ïŒL20
æ£ããæ©èœãããããã«ç§ãèŠã€ããå¯äžã®æ¹æ³ã¯ã setState
åŒã³åºããšãã«ãªããžã§ã¯ãas IState
ãæ瀺çã«å
¥åããããšã§ããããã¯å°ãäžäŸ¿ã§ãå¿ããã¡ã§ãã
ç§ã¯å€æŽã®è«ççæ ¹æ ãæ£ç¢ºã«ç解ããŠããŸããããç¶æ ãæäœãããšãã«ããªãéèŠãªæ¹æ³ã§åå®å šæ§ãç Žã£ãããã§ãã®ã§ãããã解決ããæ¹æ³ãããã°çŽ æŽãããã§ãããïŒ
ããããšãã
ãã
ãããç¹°ãè¿ããŸããã Partial
ã䜿çšãããšããã®é¢ä¿æ
å ±ãããé©åã«ä¿ãããã®ã§ã䜿çšããã»ãããããšæããŸãã
ééããªãã Pick
ãæ£ãããªãã¡ã¯ã¿ãªã³ã°ãããªãããšã¯ããªãã¡ã¯ã¿ãªã³ã°ã³ãŒãã®å¶é/ãã°ã§ãããæ¹åãããå¯èœæ§ããããŸããã Pick
ãhttpsïŒ//ã®åå®å
šæ§ãæäŸããŠãããšã¯ãŸã ä¿¡ããŠããŸããPartial
ã¯undefined
Partial
ãèš±å¯ããŸããã undefined
ã¯æ³å®ãããŠããªãããããŠãŒã¶ãŒã¯ãããè¡ããªãããã«æ³šæããå¿
èŠããããŸããã Pick
ã¯äœã§ãèš±å¯ãPick
ã代ããã«ç©ºã®ã€ã³ã¿ãŒãã§ã€ã¹ãçæããŸããããã¯äœã§ãåãå
¥ããŸãã
https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18365#issuecomment -318388471ã«é¢ããŠã¯ãããã¯è¶ éããããã£ãã§ãã«ãŒã®ãã°ã§ããå¯èœæ§ããããŸããïŒ ãããšãã2.3ãŸãã¯2.4ã§è¶ éããããã£ãã§ãã«ãŒãå³ãããªãåã«ããããã¹ããããŸãããïŒå¿ããŸããïŒïŒ
ããã§æ°ä»ãããã1ã€ã®åé¡ã¯ãã³ã³ããŒãã³ãã«ç¶æ
ã¿ã€ãããªãå ŽåïŒã€ãŸãã React.Component
ãžã®ã¿ã€ããã©ã¡ãŒã¿ãŒã1ã€ãããªãå ŽåïŒããŸãã¯ç¶æ
ã¿ã€ãã空ã®å ŽåïŒ {}
ïŒãTypescriptã§åŒãç¶ãèš±å¯ãããããšã§ãããšã©ãŒãã¹ããŒããã«setState
ãåŒã³åºããšãç§ã«ã¯æ£ãããªãããã§ãâhttpsïŒ//github.com/tomduncalf/react-types-issue/blob/master/Test2.tsxãåç
§ããŠ
ããŒã·ã£ã«ãµãŠã³ãã䜿çšãããœãªã¥ãŒã·ã§ã³ã¯ãç§ãããæãŸããã§ããèªåã§ããããé©çšããŠãã©ã®ããã«æ©èœãããã確èªããããšãã§ããŸãã
ããããšãã
ãã
ããã«ã¡ã¯ãã¿ããªïŒ
çç±ã¯ããããŸãããã setState
宣èšãåäžã®å®£èšã«çµåãããšã次ã®ããã«ãªããŸãã
setState<K extends keyof S>(state: ((prevState: Readonly<S>, props: P) => Pick<S, K>) | Pick<S, K>, callback?: () => any): void;
ããã¯ç§ã«ãšã£ãŠæåŸ éãã«æ©èœããŸãïŒ
import * as React from 'react';
export class Comp extends React.Component<{}, { foo: boolean, bar: boolean }> {
public render() {
this.handleSomething();
return null;
}
private handleSomething = () => {
this.setState({ foo: '' }); // Type '""' is not assignable to type 'boolean'.
this.setState({ foo: true }); // ok!
this.setState({ foo: true, bar: true }); // ok!
this.setState({}); // ok!
this.setState({ foo: true, foo2: true }); // Object literal may only specify
// known properties, and 'foo2' does not exist in type
this.setState(() => ({ foo: '' })); // Property 'foo' is missing in type '() => { foo: string; }'.
this.setState(() => ({ foo: true })); // ok!
this.setState(() => ({ foo: true, bar: true })); // ok!
this.setState(() => ({ foo: true, foo2: true })); // Property 'foo' is missing in type
// '() => { foo: true; foo2: boolean; }'
this.setState(() => ({ foo: '', foo2: true })); // Property 'foo' is missing in
// type '() => { foo: string; foo2: boolean; }'.
this.setState(() => ({ })); // ok!
};
}
ããã¯å ã®åé¡ãä¿®æ£ããã®ã«ååã«å€æŽã§ããŸããïŒ
@mctepãã
ãããŠãç§ãããªãã®ããããšãå°ãæ¡åŒµããŠãå Žæã«ãã£ãŠã¯Pick<S, K>
ã§ã¯ãªãPartial<S> & Pick<S, K>
ã«ãªããšãã€ã³ããªã»ã³ã¹ã¯ããªãã«ããŒåãææ¡ããŸãã æ®å¿µãªãããããŒåã¯ããããã£å€ããäœã|æªå®çŸ©ãã§ãããšèšã£ãŠããŸããããããã³ã³ãã€ã«ãããšãããããããããŸãã
declare class Component<P, S> {
setState<K extends keyof S>(state: ((prevState: Readonly<S>, props: P) => (Partial<S> & Pick<S, K>)) | (Partial<S> & Pick<S, K>), callback?: () => any): void;
}
interface State {
foo: number;
bar: string;
baz?: string;
}
class Foo extends Component<{}, State> {
constructor() {
super();
this.setState(() => { // error
return {
foo: undefined
}
});
this.setState({ // error
foo: undefined
})
this.setState({
foo: 5,
bar: "hi",
baz: undefined
})
}
}
ãã®å€æŽã¯ä»æ¥ã®åŸåã«è¡ããŸã
æè¿ã®ãä¿®æ£ãã«ããã setState()
ã³ãŒã«ããã¯å
ã®è€æ°ã®returnã¹ããŒãã¡ã³ãã§åé¡ãçºçããŠããŸãã
TypescriptïŒ2.6.2ãstrictFunctionTypesããé€ããã¹ãŠã®ãstrictããªãã·ã§ã³ãæå¹ã«ãªã£ãŠãã
ã¿ã€ã/åå¿ïŒ16.0.30
ã³ãŒãäŸïŒ
interface TestState {
a: boolean,
b: boolean
}
class TestComponent extends React.Component<{}, TestState> {
private foo(): void {
this.setState((prevState) => {
if (prevState.a) {
return {
b: true
};
}
return {
a: true
};
});
}
}
ã³ã³ãã€ã©ãšã©ãŒïŒ
error TS2345: Argument of type '(prevState: Readonly<TestState>) => { b: true; } | { a: true; }' is not assignable to parameter of type '((prevState: Readonly<TestState>, props: {}) => Pick<TestState, "b"> & Partial<TestState>) | (Pick<TestState, "b"> & Partial<TestState>)'.
Type '(prevState: Readonly<TestState>) => { b: true; } | { a: true; }' is not assignable to type 'Pick<TestState, "b"> & Partial<TestState>'.
Type '(prevState: Readonly<TestState>) => { b: true; } | { a: true; }' is not assignable to type 'Pick<TestState, "b">'.
Property 'b' is missing in type '(prevState: Readonly<TestState>) => { b: true; } | { a: true; }'.
522 this.setState((prevState) => {
~~~~~~~~~~~~~~~~
ãã®å€æŽã®çµæãšããŠ@UselessPicklesã«ãã£ãŠèª¬æãããåé¡ã確èªã§ããŸãã
ç§ã¯ãããåžžã«åé¡ã§ãã£ãããšãããªã確信ããŠããŸãã
ç§ã¯ãããåžžã«åé¡ã§ãããšã¯éããªãããšãããªã確信ããŠããŸãã setState()
ã³ãŒã«ããã¯ã«è€æ°ã®returnã¹ããŒãã¡ã³ããããã2ãæ以äžåé¡ãªãã³ã³ãã€ã«ãããŠãããããžã§ã¯ãããããŸãã ç§ã¯2é±éããšã«NPMäŸåé¢ä¿ã®ã¢ããã°ã¬ãŒãã«è¿œãã€ããŠããŸãããããã®ã³ã³ãã€ã©ãšã©ãŒã¯ãtypes / reactã®ææ°ããŒãžã§ã³ã«ã¢ããã°ã¬ãŒãããåŸã®ä»æ¥ããçºçãå§ããŸããã 以åã®ããŒãžã§ã³ã§ã¯ããã®ã³ã³ãã€ã©ãšã©ãŒã¯çºçããŸããã§ããã
ããŒã·ã£ã«ããããã¯ã«å€æŽãããŠä»¥æ¥ãåé¡ãçºçããŠããŸãã åé¿çã¯ãè¿ãäºå®ã®ããŒã®ãªã¹ããsetState
ã®æ±çšãã©ã¡ãŒã¿ãŒã«æå®ããããšã§ããããã®å Žåã¯åžžã«ãã¹ãŠã®ããŒãè¿ãå¿
èŠããããŸã...
ãã®ãããªå Žåã«ç§ãè¡ãããšã¯ãå€æŽãããŠããªãããŒãkey: prevState.key
ã«èšå®ããŠãåžžã«ãã¹ãŠã®ããŒãè¿ãããprevStateïŒ { ...prevState, newKey: newValue }
ïŒã§ã¹ãã¬ãããè¿ãããšã§ãã
ãã¶ããç§ã¯å®éã«ã以åã¯å¶ç¶ã«æ©èœããŠãããããå ·äœçãªãšããžã±ãŒã¹ãã³ãŒãã«æã£ãŠããŸããïŒ ç§ã®ãããžã§ã¯ãã®å®éã®äŸã¯æ¬¡ã®ãããªãã®ã§ã空ã®ãªããžã§ã¯ããè¿ããïŒç¶æ ãå€æŽããªãããïŒã空ã§ãªããªããžã§ã¯ããè¿ããŸãã
interface TestState {
a: boolean,
b: boolean
}
class TestComponent extends React.Component<{}, TestState> {
private foo(newValue: boolean): void {
this.setState((prevState) => {
if (prevState.a === newValue) {
// do nothing if there's no change
return { };
}
return {
a: newValue,
// force "b" to false if we're changing "a"
b: false
};
});
}
}
return null
ãšreturn undefined
ããç¶æ
ãå€æŽããªãå Žåã®å®å
šã«èš±å®¹å¯èœãªæ»ãå€ã§ãïŒ Object.assign
ãééããããã this.state
ã¯å€æŽãããŸããïŒã
ç§ã«æãåºãããŠãã ãããçŸåšã®çœ²åã¯ãããã®ã©ã¡ããèš±å¯ããŠããŸããã null
ã¯ãå°ãªããšãreturn
ã誀ã£ãŠå¿ããŠããŸãå¯èœæ§ããããã®ã§ã¯ãªããããæ»ãå€ãšããŠèš±å¯ããå¿
èŠããããŸãã
ãšã«ããã眲åããããŸããªå ŽåãTypeScriptã¯ãœãŒã¹é ã§æåã®return
ã¹ããŒãã¡ã³ãã®ã¿ãéžæããããã䜿çšããŠãžã§ããªãã¯ãã©ã¡ãŒã¿ãŒãå°åºããããã§ãã åçŽãªãžã§ããªãã¯ïŒ Array
ãPromise
ïŒã®åãããŒãžã§ããããã§ãããã³ã³ããã¹ãåãPick
ãããªãããåã®å Žåã¯ãããããããŒãžããããšã¯ãããŸããã
ææ°ã®ã¿ã€ãã®éæ©èœããŒãžã§ã³ã§ããã€ãã®ãªã°ã¬ãã·ã§ã³ãçºçããŠããŸãã ç¹ã«ãåŒæ°ãæž¡ããšãã®ãç¶æ ãåŒæ°ã¿ã€ãã¯æ¬¡ã®ããã«å€æŽãããŸããã
setState
ïŒç¶æ ïŒããã¯ãã³ãŒã«ããã¯ïŒïŒïŒïŒ=>ä»»æïŒïŒvoid;
ã«ïŒ
ç¶æ ïŒïŒïŒprevStateïŒReadonly \
ãpropsïŒPïŒ=>ïŒPickïŒPartial \ïŒïŒ|
https://github.com/DefinitelyTyped/DefinitelyTyped/commit/62c2219a6ed6dc34ea969b8c2c87a41d31002660#diff -96b72df8b13a8a590e4f160cbc51f40c
& Partial<S>
ã®è¿œå ã¯ã以åã¯æ©èœããŠãããã®ãå£ããŠããããã§ãã
æå°éã®åçŸã¯æ¬¡ã®ãšããã§ãã
export abstract class ComponentBaseClass<P, S = {}> extends React.Component<P, S & { baseProp: string }>
{
foo()
{
this.setState( { baseProp: 'foobar' } );
}
}
ããã¯ãšã©ãŒã§å€±æããŸãïŒ
ïŒ429,18ïŒïŒã¿ã€ã '{basePropïŒ "foobar";ã®åŒæ° } 'ã¯ã¿ã€ã'ã®ãã©ã¡ãŒã¿ã«å²ãåœãŠãããšãã§ããŸããïŒïŒprevStateïŒèªã¿åãå°çš
ã¿ã€ã '{basePropïŒ "foobar";}'ã¯ã¿ã€ã 'PickïŒ'ã«å²ãåœãŠãããšãã§ããŸããPartialType
ç¶æ
ã¿ã€ããS &{ baseProp: string }
ãã{ baseProp: string }
ã«å€æŽãããšããšã©ãŒããªããªããŸãïŒãã ããSã¿ã€ããæå®ããå®éã®ã¯ã©ã¹ã¯ç ŽæããŸãïŒã
ããã¯é¢çœãã å€æŽã®äžéšãããŒã«ããã¯ããŠãäžéšãéžæã§ããŸãã
ç§ã¯ããªããå ±åããããšã¯TSã®ãã°ã®ããã«èããããšèšããŸããå ·äœçã«ã¯ïŒ
ã¿ã€ã '{basePropïŒ "foobar"; } 'ã¯ã¿ã€ã' Partialã«å²ãåœãŠãããšãã§ããŸãã
倧äžå€«ã SãšbasePropã®éã«é¢ä¿ããªããããTSã¯äœãèµ·ããŠããã®ãããããªããããããŸããã
ã¿ã€ã{ basePropïŒnumber }ã®Sãæž¡ãããšãã§ããŸãããã®å ŽåãbasePropã«æååãå²ãåœãŠãããšã¯ã§ããŸããã
ãããããSãbasePropããŒãžã§ã³ãæ¡åŒµããå Žåã¯ã©ãã§ããããã
ç§ã¯ä»¥åã«ãã®ãããªããšãè©ŠããŸããïŒ
interface BaseState_t
{
baseProp: string
}
export abstract class ComponentBaseClass<P, S extends BaseState_t> extends React.Component<P, S >
{
foo()
{
this.state.baseProp;
this.setState( { baseProp: 'foobar' } );
}
}
ã¢ã¯ã»ã¹ã¯æ£åžžã§ãããsetStateåŒã³åºãã«ãåããšã©ãŒããããŸãã
ã¿ã€ãã®åŒæ° '{basePropïŒ "foobar"; } 'ã¯ã¿ã€ã'ã®ãã©ã¡ãŒã¿ã«å²ãåœãŠãããšãã§ããŸããïŒïŒprevStateïŒReadonly \
ãpropsïŒPïŒ=> PickïŒPartial \ïŒ|} 'ã¯ã¿ã€ã' PickïŒPartial \å²ãåœãŠãããšã¯ã§ããŸãã'ã«ã¿ã€ã '{basePropïŒ "foobar";
ãããæ§é åããã®ã¯ããããè¯ãæ¹æ³ã§ã¯ãããŸãã-çµå±ã®ãšãããäžéšã®åã¯ã©ã¹ã¯ãåºæ¬ã¯ã©ã¹ã®å€æ°ãšè¡çªããç¶æ å€æ°ã宣èšããå¯èœæ§ããããŸãã ãããã£ãŠãtypescriptã¯ãããã§äœãèµ·ãããããããªããšäžå¹³ãèšãã®ãæ£ãããããããŸããã ãããããããã®å°éå ·ã«ã¢ã¯ã»ã¹ããããšã«åé¡ããªãã®ã¯å¥åŠã§ãã
ããŒãã ããã¯ééããªãTSã®ãã°ã®ããã«æããŸãã
ä»æ¥ã¯ããã§éãã§ãããããïŒPartialãåãåºããŸãã
ããããã¹ãã±ãŒã¹ãšããŠè¿œå ããã€ã³ããªã»ã³ã¹ã幞ãã«ããããã®å¥ã®ã¢ã€ãã¢ãè©ŠããŠã¿ãŸã
ããã
ããã§åãåé¡...
export interface ISomeComponent {
field1: string;
field2: string;
}
interface SomeComponentState {
field: string;
}
export class SomeComponent<
TProps extends ISomeComponent = ISomeComponent,
TState extends SomeComponentState = SomeComponentState> extends React.Component<TProps, TState>{
doSomething() {
this.setState({ field: 'test' });
}
render() {
return (
<div onClick={this.doSomething.bind(this)}>
{this.state.field}
</div>
);
}
}
setStateã®ãšã©ãŒïŒ
TS2345 (TS) Argument of type '{ field: "test"; }' is not assignable to parameter of type '((prevState: Readonly<TState>, props: TProps) => Pick<TState, "field"> & Partial<TState>) | (Pick...'.
Type '{ field: "test"; }' is not assignable to type 'Pick<TState, "field"> & Partial<TState>'.
Type '{ field: "test"; }' is not assignable to type 'Partial<TState>'.
ãã®å€æŽåŸããšã©ãŒãçºçãå§ããŸããã ããŒãžã§ã³16.0.10ã§ã¯æ£åžžã«åäœããŸããã
Typescriptã«ã¯ããã€ãã®é¢é£ããåé¡ããããèšèšã©ããã«æ©èœããããã«ããããéããŸããã
https://github.com/Microsoft/TypeScript/issues/19388
ããã§ããã€ãã®äŸã®èŠç¹ãäœæããŸããïŒ https ïŒ
åäœã¯ãŸã å¥åŠã«èŠããŸããã ç¹ã«ããã£ã¹ããªãã§åºæ¬ã¯ã©ã¹ãšããŠåæå®ãããå€æ°ã«å²ãåœãŠãŠãåé¡ãªãåãåŒã³åºããè¡ãããšãã§ããŸãã ãã®åé¡ã¯ãå²ãåœãŠãšæ¯èŒã2ã€ã®ç°ãªããã®ã§ããããšã瀺åããŠããããã§ãã
ããªããã¡ãå¿ããŠããŸããã ããã«ä¿®æ£ãããŸã
åç §ãããPRã¯ãã®åé¡ã解決ããã¯ãã§ãã ãŸãããã®ãšããžã±ãŒã¹ãåã³å£ããªãããã«ä¿è·ãããã¹ããè¿œå ããŸããã
@ericandersonè¿ éãªå¯Ÿå¿ã«æè¬ããŸã:)
æ°ããä¿®æ£ã«ã¯å¶é/æ¬ ç¹ããããŸããïŒ
ç§ãçŸåšç¥ã£ãŠãããã®ã¯ãããŸããã ã€ã³ããªã»ã³ã¹ãç¶æããããšãã§ããŸããïŒããã€ãã®ãšããžã±ãŒã¹ã解決ãããããå®éã«ã¯ä»¥åãããåªããŠããŸãïŒã
詳述ãããšã & Partial<S>
解決çã¯ãã€ã³ããªã»ã³ã¹ãã ãŸããŠå¯èœãªãã©ã¡ãŒã¿ãæããã«ããããšã§ããããããã¯X | undefined
ãšè¿°ã¹ãããšã«ãã£ãŠè¡ãããŸããã ãã¡ããããã¯ã³ã³ãã€ã«ã«å€±æããŸãããå°ãæ··ä¹±ããŸããã | S
ååŸãããšãã€ã³ããªã»ã³ã¹ãä¿®æ£ããããã¹ãŠã®æ£ãããã©ã¡ãŒã¿ãŒãææ¡ããã誀ã£ãã¿ã€ãã衚瀺ãããªããªããŸãã
setState
ã³ãŒã«ããã¯ããã®å¯èœãªæ»ãå€ãšããŠnull
ãè¿œå ããããšãæ€èšããŸããïŒ return;
ãäœæããã«ãç¶æ
ãå€æŽããããªãç¶æ
ã«æ»ãããšãã§ãããã®ãŸãæå¹ã§ãïŒãã代ããã«åæšè«ãå®å
šã«æŸæ£ããããŒãšããŠnever
ãŸããð¢
ä»ã®ãšãããå®éã«ç¶æ
ã®æŽæ°ãã¹ããããããã³ãŒã«ããã¯ã§ã¯ã return null!
ãŸãã ãã®æ»ãå€ã®never
åã«ãããTypeScriptã¯ãžã§ããªãã¯åæšè«ã®æ»ãå€ãç¡èŠããŸãã
ããã«ã¡ã¯ãã¿ããª...
æåŸã®ã³ãããã§åé¡ãä¿®æ£ãããŸããã
è¿
éãªè¿çã«æè¬èŽããŸã ïŒïŒ
ã©ã®ããŒãžã§ã³ã§ä¿®æ£ãããŠããŸããïŒ npmã«å ¬éãããŠããŸããïŒ @UselessPicklesãèŠã€ãã£ãããã«ãsetStateã®ã³ãŒã«ããã¯ããŒãžã§ã³ãæ»ãå€ã«ããããã£ã®äžäžèŽããããšèšã£ãŠããå ŽåããããŸãã
ææ°ã®@types / reactã§è¯ãã¯ãã§ã
15ã·ãªãŒãºãš16ã·ãªãŒãºã§ä¿®æ£ããŸãã
import produce from 'immer';
interface IComponentState
{
numberList: number[];
}
export class HomeComponent extends React.Component<ComponentProps, IComponentState>
Reactã®å€ãåã®å®çŸ©ã
// We MUST keep setState() as a unified signature because it allows proper checking of the method return type.
// See: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18365#issuecomment-351013257
// Also, the ` | S` allows intellisense to not be dumbisense
setState<K extends keyof S>(
state: ((prevState: Readonly<S>, props: P) => (Pick<S, K> | S)) | (Pick<S, K> | S),
callback?: () => void
): void;
..ãã®ãšã©ãŒãçºçããŸãïŒ
ç§ã¯ãã®ææ¡ãè©ŠããŸããïŒ
setState<K extends keyof S>(
state:
((prevState: Readonly<S>, props: P) => (Partial<S> & Pick<S, K>))
| (Partial<S> & Pick<S, K>),
callback?: () => any
): void;
Intellisenseã¯ãReactã®ç¶æ
ããããããã£ãæ€åºã§ããããã«ãªããŸããã ãã ããæ€åºãããããããã£ã¯possibly undefined
ãšããŠèªèãããããã«ãªããŸããã
numberListãæªå®çŸ©ã§ãnull蚱容ã§ããªãå Žåã§ããnullã¢ãµãŒã·ã§ã³æŒç®åã䜿çšããå¿ èŠããããŸãã
ã¿ã€ãã»ã³ã·ã³ã°ãæ¹åããããŸã§ãå€ãã¿ã€ãå®çŸ©ã®ãŸãŸã«ããŠãããŸãã ãããŸã§ã®éãã€ããŒãããã¥ãŒã¹ã®ãžã§ããªãã¯ãã©ã¡ãŒã¿ãŒã®ã¿ã€ããæ瀺çã«èª¬æããŸãã produce<IComponentState>
ã¯ã list!
ãããæšè«ãç°¡åã§ãã
æåã®ãšã©ãŒã¯ãäœãè¿ããªãããã§ãã ããã¯setStateãã©ã®ããã«æ©èœãããã§ã¯ãããŸããã
蟲ç£ç©ã§å€æ°ãè¿ããªãå Žåã§ãæ©èœããŸãã ç§ã¯ããã®äŸïŒTypeScript以å€ïŒã«åŸããŸããïŒ
https://github.com/mweststrate/immer
onBirthDayClick2 = () => {
this.setState(
produce(draft => {
draft.user.age += 1
// no need to return draft
})
)
}
TypeScriptããã®ã³ãŒããå®è¡ã§ããªãããã«ããå¯äžã®ããšã¯ãReactåå®çŸ©ãã誀ã£ãŠåãæšæž¬ãããŠããããšã§ãã ã¿ã€ãå®çŸ©ã¯numberList does not exist on type Pick<IComponentState, never>
ãšã©ãŒãå ±åããŸãã çæç©ã®ãžã§ããªãã¯ãã©ã¡ãŒã¿ãŒãã€ãŸãproduce<IComponentState>
åãæ瀺çã«æž¡ãããšã§ãã³ã³ãã€ã«ãšã©ãŒããªããããšãã§ããŸãã
蟲ç£ç©ã§å€æ°ãè¿ããŠãReactåå®çŸ©ãåãæšæž¬ããã®ã«åœ¹ç«ã€ãã©ããã確èªããããšããŸãããïŒã²ãããšåµã®åé¡ã§ãïŒãããã§ãReactåå®çŸ©ãç¶æ ã®æ£ããåãæ€åºããæ¹æ³ã¯ãããŸããã ãããã£ãŠããã©ããã®ã€ã³ããªã»ã³ã¹ã¯è¡šç€ºãããŸããã
ãããã¯ãã³ã³ãã€ã©ããã®æåŸ
ãééã£ãŠãããããããŸãã:)ã³ã³ãã€ã©ã¯ã³ãŒããè£è¿ãã«åŠçãããããsetStateã®åã«åºã¥ããŠãã©ããå€æ°ã®åãäœæã§ããŸããã ããããææ¡ãããåå®çŸ©ã¯ãã³ã³ãã€ã©ãå€éšããã³ãŒããåŠçã§ããå€éšã³ãŒãïŒ setState
ïŒããå
éšã³ãŒãïŒ produce
ïŒã«æž¡ãããšãã§ããæé©ãªåãéžæã§ãããšç§ã«æãããŸããã
setState<K extends keyof S>(
state:
((prevState: Readonly<S>, props: P) => (Partial<S> & Pick<S, K>))
| (Partial<S> & Pick<S, K>),
callback?: () => any
): void;
äžèšã®åå®çŸ©ã䜿çšãããšãã³ã³ãã€ã©ã¯ãã©ããã«numberList
ããããã£ãããããšãæ€åºã§ããŸãã ãã ãã possibly undefined
ãšããŠæ€åºãããŸãã
ããã«ããããåããšãsetStateã®åå®çŸ©ã«S
ãè¿œå ããããšã§ãã³ã³ãã€ã©ãç¶æ
ã®åãæž¡ããŠãã©ãããçæã§ããããã«ããŸããã
setState<K extends keyof S>(
state:
((prevState: Readonly<S>, props: P) => (Partial<S> & Pick<S, K> & S))
| (Partial<S> & Pick<S, K>),
callback?: () => any
): void;
ã³ãŒãã¯çŸåšã³ã³ãã€ã«äžã§ã:)
ãšã©ãŒã¯setStateã§ã¯ãªãã蟲ç£ç©ã®å éšã«ãããŸãã 蟲ç£ç©ã®ã¿ã€ãå®çŸ©ã¯äœã§ããïŒ
äžèšã®ç§ã®PRã¯ãDefinitelyTypedã®ãã¹ãã¹ã¯ãªããã§ãšã©ãŒãçºçããŸãããããŒã«ã«ã§ãã¹ãããŸããã§ããã ã ããç§ã¯ä»ãããããŒã«ã«ã§ãã¹ãããŠããŸãã
ãããã€ããŒ/ãããã¥ãŒã¹ã¿ã€ãã®å®çŸ©ã§ãã
/**
* Immer takes a state, and runs a function against it.
* That function can freely mutate the state, as it will create copies-on-write.
* This means that the original state will stay unchanged, and once the function finishes, the modified state is returned.
*
* If the first argument is a function, this is interpreted as the recipe, and will create a curried function that will execute the recipe
* any time it is called with the current state.
*
* <strong i="7">@param</strong> currentState - the state to start with
* <strong i="8">@param</strong> recipe - function that receives a proxy of the current state as first argument and which can be freely modified
* <strong i="9">@param</strong> initialState - if a curried function is created and this argument was given, it will be used as fallback if the curried function is called with a state of undefined
* <strong i="10">@returns</strong> The next state: a new state, or the current state if nothing was modified
*/
export default function<S = any>(
currentState: S,
recipe: (this: S, draftState: S) => void | S
): S
// curried invocations with default initial state
// 0 additional arguments
export default function<S = any>(
recipe: (this: S, draftState: S) => void | S,
initialState: S
): (currentState: S | undefined) => S
// 1 additional argument of type A
export default function<S = any, A = any>(
recipe: (this: S, draftState: S, a: A) => void | S,
initialState: S
): (currentState: S | undefined, a: A) => S
// 2 additional arguments of types A and B
export default function<S = any, A = any, B = any>(
recipe: (this: S, draftState: S, a: A, b: B) => void | S,
initialState: S
): (currentState: S | undefined, a: A, b: B) => S
// 3 additional arguments of types A, B and C
export default function<S = any, A = any, B = any, C = any>(
recipe: (this: S, draftState: S, a: A, b: B, c: C) => void | S,
initialState: S
): (currentState: S | undefined, a: A, b: B, c: C) => S
// any number of additional arguments, but with loss of type safety
// this may be alleviated if "variadic kinds" makes it into Typescript:
// https://github.com/Microsoft/TypeScript/issues/5453
export default function<S = any>(
recipe: (this: S, draftState: S, ...extraArgs: any[]) => void | S,
initialState: S
): (currentState: S | undefined, ...extraArgs: any[]) => S
// curried invocations without default initial state
// 0 additional arguments
export default function<S = any>(
recipe: (this: S, draftState: S) => void | S
): (currentState: S) => S
// 1 additional argument of type A
export default function<S = any, A = any>(
recipe: (this: S, draftState: S, a: A) => void | S
): (currentState: S, a: A) => S
// 2 additional arguments of types A and B
export default function<S = any, A = any, B = any>(
recipe: (this: S, draftState: S, a: A, b: B) => void | S
): (currentState: S, a: A, b: B) => S
// 3 additional arguments of types A, B and C
export default function<S = any, A = any, B = any, C = any>(
recipe: (this: S, draftState: S, a: A, b: B, c: C) => void | S
): (currentState: S, a: A, b: B, c: C) => S
// any number of additional arguments, but with loss of type safety
// this may be alleviated if "variadic kinds" makes it into Typescript:
// https://github.com/Microsoft/TypeScript/issues/5453
export default function<S = any>(
recipe: (this: S, draftState: S, ...extraArgs: any[]) => void | S
): (currentState: S, ...extraArgs: any[]) => S
/**
* Automatically freezes any state trees generated by immer.
* This protects against accidental modifications of the state tree outside of an immer function.
* This comes with a performance impact, so it is recommended to disable this option in production.
* It is by default enabled.
*/
export function setAutoFreeze(autoFreeze: boolean): void
/**
* Manually override whether proxies should be used.
* By default done by using feature detection
*/
export function setUseProxies(useProxies: boolean): void
@ericandersonãPartial
代ããã«Pick
ã䜿çšãããçç±ã«ã€ããŠã®è°è«ãæããŠããã ããŸããïŒ ããã¯ç§ã«äœæéãã®æ²ãã¿ãåŒãèµ·ãããŸããïŒã³ãŒã«ããã¯ããŒãžã§ã³ã§ã¯ãªãããã¬ãŒã³ãªsetState(obj)
ã䜿çšããŸãïŒããããŠä»ã®ãšããç§ã¯åé¿çãšããŠthis.setState(newState as State)
ã䜿çšããŸãã äœãã足ããªãã®ã§ããªãå€æŽãããã®ããç解ãããã ãã§ãã
ããã«ã¡ã¯@ericanderson ã
ææ°ã®å®çŸ©ã«åé¡ããããŸãã
ç§ã®ãŠãŒã¹ã±ãŒã¹ã¯ç°¡åã«æ¬¡ã®ããã«ãªããŸãã
interface AppState {
valueA: string;
valueB: string;
// ... something else
}
export default class App extends React.Component <{}, AppState> {
onValueAChange (e:React.ChangeEvent<HTMLInputElement>) {
const newState: Partial<AppState> = {valueA: e.target.value}
if (this.shouldUpdateValueB()) {
newState.valueB = e.target.value;
}
this.setState(newState); // <-- this leads to a compiling error
}
// ... other methods
}
ãšã©ãŒã¡ãã»ãŒãžã¯æ¬¡ã®ãããªãã®ã§ãã
Argument of type 'Partial<AppState>' is not assignable to parameter of type 'AppState | ((prevState: Readonly<AppState>, props: {}) => AppState | Pick<AppState, "valueA" | "v...'.
Type 'Partial<AppState>' is not assignable to type 'Pick<AppState, "valueA" | "valueB" | "somethingElse">'.
Types of property 'valueA' are incompatible.
Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.
Partial<AppState>
ã¯setState
眲åãšäºææ§ããªãããã§ãã ãã¡ãããç§ã¯æ¬¡ã®ãããªã¿ã€ãã¢ãµãŒã·ã§ã³ã«ãã£ãŠããã解決ã§ããŸã
this.setState(newState as Pick<AppState, 'valueA' | 'valueB'>)
ããããããã¯çæ³çã§ã¯ãããŸãããçç±ã¯æ¬¡ã®ãšããã§ãã
1ïŒãã®æ§æã¯éåžžã«åé·ã§ã
2ïŒããã«éèŠãªããšã«ãåã¢ãµãŒã·ã§ã³ã¯ç§ã®å®éã®ããŒã¿ã«éåããå¯èœæ§ããããŸãã ããšãã°ã newState as Pick<AppState, 'somethingElse'>
ããã§ãã¯ã«åæ ŒããŸãããç§ã®ããŒã¿ã«ã¯é©åããŸããã
éšåçã ãšæããŸã
ç§ã®ææ¡ãæ€èšãããã誀解ãããå Žåã¯ææããŠããã ããŸãããã ããããšãããããŸããïŒ
ããã¯æåã¯æ¬åœã«å€ãå€æŽã§ãã ãããã£ãŠãä»ã®èª°ããæè¿ãããå€æŽããªãéããããããééã£ãæšãå ããŠããã§ãããã
ããã¯èšã£ãã éšåçã«ã¯æªå®çŸ©ã®å€ãèš±å¯ããŸãã
const aïŒPartial <{fooïŒstring}> = {fooïŒundefined}
aã¯æå¹ã§ãããæããã«ãç¶æ ãæŽæ°ããçµæãäžå¯èœã§ãããšå®£èšããå Žåã§ããfooãæªå®çŸ©ã®ç¶æ ã«ãªããŸãã
ãããã£ãŠãããŒã·ã£ã«ãããã¯ã«å²ãåœãŠãããšã¯ã§ããŸããã ãããŠãããã¯ã¯ããªãã®ã¿ã€ããåãã€ããªãããã«ããããã®æ£ããçãã§ã
ç§ã¯ãããèš±ããªããšæããŠããŸãïŒ
setState((prevState) => {
if (prevState.xyz) {
return { foo: "" };
}
return { bar: "" };
});
è¶ å¶éçã§ãã
@Kovenskyã®åé¿çã¯ãç§ãç¥ã£ãŠããå¯äžã®è³¢æãªåé¿çã§ãããããã§ãæžãã®ã¯èŠçã§ãã
ãã®ïŒç§ãèšãã ããïŒããªãäžè¬çãªãã¿ãŒã³ããµããŒãããããã«ã§ããããšã¯ãããŸããïŒ
ã§ããå¯äžã®ããšã¯ãåå®å šæ§ãåãé€ãããšã§ã
誰ããPick<S, K> | S | null
ã®çç±ã説æã§ããŸããïŒ
setState<K extends keyof S>(
state: ((prevState: Readonly<S>, props: Readonly<P>) => (Pick<S, K> | S | null)) | (Pick<S, K> | S | null),
callback?: () => void
): void;
Tbh K
ãkeyof S
ãšããŠå®çŸ©ãããŠããã®ã§ãäžèšã®çœ²åãéšåçãªç¶æ
ã®æŽæ°ã§ãæ©èœããçç±ã¯ä»ã§ãããããŸããããããã£ãŠã Pick<S, K>
åºæ¬çã«S
åäœæããŸããïŒ
Partial<S> | null
ããã®ä»äºãããã¹ãã§ã¯ãããŸãããïŒ
setState(
state: ((prevState: Readonly<S>, props: Readonly<P>) => (Partial<S> | null)) | (Partial<S> | null),
callback?: () => void
): void;
誰ãã説æã§ããŸãã...
ããã€ãã®åçãæ確ã«èª¬æãããŠããŸãã
setState((prevState) => { if (prevState.xyz) { return { foo: "" }; } return { bar: "" }; });
è¶ å¶éçã§ãã
@Kovenskyã®åé¿çã¯ãç§ãç¥ã£ãŠããå¯äžã®è³¢æãªåé¿çã§ãããããã§ãæžãã®ã¯èŠçã§ãã
ãã®æ£ç¢ºãªåé¡ãçºçããã°ããã§ãããã¹ã¬ããã«Kovenskyãžã®åç §ã衚瀺ãããŸããïŒèª°ãããŠãŒã¶ãŒåãå€æŽããå¯èœæ§ããããŸããïŒïŒã 誰ããç§ã«çŸåšæšå¥šãããŠããåé¿çãæããŠããããŸãã
@ timrobinson33ãã®ã³ã¡ã³ãã¯ãåé¿çã説æããŠããŸãhttps://github.com/DefinitelyTyped/DefinitelyTyped/issues/18365#issuecomment -351884578
ãããŠãããã¯ã§ããã«ã€ããŠããå¿é ããå¿ èŠããªãã®ã¯è¯ãããšã§ãð
@ timrobinson33ãã®ã³ã¡ã³ãã¯åé¿çã説æããŠããŸãïŒ18365ïŒã³ã¡ã³ãïŒ
ã©ããããããšãããããŸããã çµå±ãããã€ãã®ãã¹ãsetStateãè€æ°ååŒã³åºãããšãæå³ããŸããã
If
ã¹ããŒãã¡ã³ããå€éšã«ããããã€ãã®å°ããªsetStateåŒã³åºããšããŠãç§ã®ã³ãŒãã¯èŠæ ããè¯ããšæããŸããã
ããã¯å®éã«ã¯ããã¯ã®æäœæ¹æ³ãšäŒŒãŠãããšæããŸããç¶æ ã¯ãåå¥ã«æŽæ°ããããã€ãã®å°ããªãã®ãšèŠãªãããŸãã
æãåèã«ãªãã³ã¡ã³ã
æè¿ã®ãä¿®æ£ãã«ããã
setState()
ã³ãŒã«ããã¯å ã®è€æ°ã®returnã¹ããŒãã¡ã³ãã§åé¡ãçºçããŠããŸããTypescriptïŒ2.6.2ãstrictFunctionTypesããé€ããã¹ãŠã®ãstrictããªãã·ã§ã³ãæå¹ã«ãªã£ãŠãã
ã¿ã€ã/åå¿ïŒ16.0.30
ã³ãŒãäŸïŒ
ã³ã³ãã€ã©ãšã©ãŒïŒ