рдореБрдХреНрддрд┐ - рд╕реНрдХреВрдмрд╛ рдбрд╛рдЗрд╡рд┐рдВрдЧ рдХреЗ рдмрд┐рдирд╛ рд╕реНрдХреВрдмрд╛ рдбрд╛рдЗрд╡рд┐рдВрдЧред рдЧреЛрддрд╛рдЦреЛрд░ рдЖрд░реНрдХрд┐рдорд┐рдбреАрдЬ рдХреЗ рдХрд╛рдиреВрди рдХреЛ рдорд╣рд╕реВрд╕ рдХрд░рддрд╛ рд╣реИ: рд╡рд╣ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдорд╛рддреНрд░рд╛ рдореЗрдВ рдкрд╛рдиреА рдХреЛ рд╡рд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдЙрд╕реЗ рдкреАрдЫреЗ рдзрдХреЗрд▓рддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдкрд╣рд▓реЗ рдХреБрдЫ рдореАрдЯрд░реЛрдВ рдХреЛ рд╕рдмрд╕реЗ рдХрдард┐рди рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдлрд┐рд░ рдЖрдкрдХреЗ рдКрдкрд░ рдкрд╛рдиреА рдХреЗ рд╕реНрддрдВрдн рдХрд╛ рджрдмрд╛рд╡ рдмрд▓ рдЧрд╣рд░рд╛ рдЬрд╛рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рдиреЗ рд▓рдЧрддрд╛ рд╣реИред рдпрд╣ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкреНрд░рдХрд╛рд░ рдХреА рдкреНрд░рдгрд╛рд▓рд┐рдпреЛрдВ рдореЗрдВ рд╕реАрдЦрдиреЗ рдФрд░ рдбрд╛рдЗрд╡рд┐рдВрдЧ рдХреА рдпрд╛рдж рджрд┐рд▓рд╛рддреА рд╣реИ - рдЬреИрд╕реЗ рд╣реА рдЖрдк рдЧреЛрддрд╛ рд▓рдЧрд╛рддреЗ рд╣реИрдВ рдпрд╣ рдереЛрдбрд╝рд╛ рдЖрд╕рд╛рди рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╣рдореЗрдВ рд╕рдордп рдкрд░ рдЙрднрд░рдирд╛ рдирд╣реАрдВ рднреВрд▓рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╡рди рдУрд╢рди рд╡рди рдмреНрд░реЗрде
рд╕реЗ рдлреЛрдЯреЛ ред рдорд┐рдЦрд╛рдЗрд▓ рдмрд╢реБрд░реЛрд╡ (saitonakamura) - рд╡рд╛рдЗрдЬрдмрд┐рдЯреНрд╕ рдореЗрдВ рд╕реАрдирд┐рдпрд░ рдлреНрд░рдВрдЯреЗрдВрдб рдЗрдВрдЬреАрдирд┐рдпрд░, рдПрдХ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдлреИрди рдФрд░ рд╢реМрдХрд┐рдпрд╛ рдлреНрд░реАрдбрд╛рдЗрд╡рд░ред рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╕реАрдЦрдиреЗ рдФрд░ рдЧрд╣рд░реА рдЧреЛрддрд╛рдЦреЛрд░реА рдХреА рдЙрдкрдорд╛ рдЖрдХрд╕реНрдорд┐рдХ рдирд╣реАрдВ рд╣реИрдВред рдорд╛рдЗрдХрд▓ рдЖрдкрдХреЛ рдмрддрд╛рдПрдВрдЧреЗ рдХрд┐ рднреЗрджрднрд╛рд╡ рд╡рд╛рд▓реЗ рд╕рдВрдШ рдХреНрдпрд╛ рд╣реИрдВ, рдкреНрд░рдХрд╛рд░ рдХреЗ рдЕрдиреБрдорд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░реЗрдВ, рдЖрдкрдХреЛ рдирд╛рдордорд╛рддреНрд░ рд╕рдВрдЧрддрддрд╛ рдФрд░ рдмреНрд░рд╛рдВрдбрд┐рдВрдЧ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреНрдпреЛрдВ рд╣реИред рдЕрдкрдиреА рд╕рд╛рдВрд╕ рдкрдХрдбрд╝реЛ рдФрд░ рдЧреЛрддрд╛ рд▓рдЧрд╛рдУредрдпрд╣рд╛рдБ рдирдореВрдирд╛ рдХреЛрдб рдХреЗ рд╕рд╛рде GitHub рдХреА рдкреНрд░рд╕реНрддреБрддрд┐ рдФрд░ рд▓рд┐рдВрдХ редрдХрд╛рдо рдХреЗ рдкреНрд░рдХрд╛рд░
рд░рдХрдо рдХреЗ рдкреНрд░рдХрд╛рд░ рдзреНрд╡рдирд┐ рдмреАрдЬрдЧрдгрд┐рддреАрдп - рдЪрд▓реЛ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдХреНрдпрд╛ рд╣реИред рдЙрдиреНрд╣реЗрдВ ReasonML рдореЗрдВ рд╡реИрд░рд┐рдПрдВрдЯ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╣рд╛рд╕реНрдХреЗрд▓ рдореЗрдВ рдЯреИрдЧ рдпреВрдирд┐рдпрди, рдФрд░ F # рдФрд░ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рднреЗрджрднрд╛рд╡рдкреВрд░реНрдг рдпреВрдирд┐рдпрдиредрд╡рд┐рдХрд┐рдкреАрдбрд┐рдпрд╛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкрд░рд┐рднрд╛рд╖рд╛ рджреЗрддрд╛ рд╣реИ: "рд░рд╛рд╢рд┐ рдХрд╛ рдкреНрд░рдХрд╛рд░ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдпреЛрдЧ рд╣реИред"- рдзрдиреНрдпрд╡рд╛рдж рдХрдкреНрддрд╛рди!рдкрд░рд┐рднрд╛рд╖рд╛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рд╣реА рд╣реИ, рд▓реЗрдХрд┐рди рдмреЗрдХрд╛рд░ рд╣реИ, рддреЛ рдЖрдЗрдП рд╕рдордЭрддреЗ рд╣реИрдВред рдирд┐рдЬреА рд╕реЗ рдЪрд▓рддреЗ рд╣реИрдВ рдФрд░ рдХрд╛рдо рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВредрдорд╛рди рд▓реАрдЬрд┐рдП рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдкреНрд░рдХрд╛рд░ рд╣реИ Task
ред рдЗрд╕рдХреЗ рджреЛ рдХреНрд╖реЗрддреНрд░ рд╣реИрдВ: id
рдФрд░ рдХрд┐рд╕рдиреЗ рдЗрд╕реЗ рдмрдирд╛рдпрд╛ рд╣реИредtype Task = { id: number, whoCreated: number }
рдЗрд╕ рддрд░рд╣ рдХрд╛ рдХрд╛рдо рдЪреМрд░рд╛рд╣рд╛ рдпрд╛ рдЪреМрд░рд╛рд╣рд╛ рд╣реИ ред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд╣рдо рдкреНрд░рддреНрдпреЗрдХ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд╕рдорд╛рди рдХреЛрдб рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВредtype Task = { id: number } & { whoCreated: number }
рдкреНрд░рд╕реНрддрд╛рд╡реЛрдВ рдХреЗ рдмреАрдЬрдЧрдгрд┐рдд рдореЗрдВ, рдЗрд╕реЗ рддрд╛рд░реНрдХрд┐рдХ рдЧреБрдгрди рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ: рдпрд╣ рдСрдкрд░реЗрд╢рди "AND" рдпрд╛ "AND" рд╣реИред рдЙрддреНрдкрд╛рдж рдХрд╛ рдкреНрд░рдХрд╛рд░ рдЗрди рджреЛ рддрддреНрд╡реЛрдВ рдХрд╛ рддрд╛рд░реНрдХрд┐рдХ рдЙрддреНрдкрд╛рдж рд╣реИредрдЦреЗрддреЛрдВ рдХреЗ рдПрдХ рд╕реЗрдЯ рдХреЗ рд╕рд╛рде рдПрдХ рд╡рд╕реНрддреБ рдХреЛ рдПрдХ рддрд╛рд░реНрдХрд┐рдХ рдЙрддреНрдкрд╛рдж рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╡реНрдпрдХреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдХрд╛рдо рдХрд╛ рдкреНрд░рдХрд╛рд░ рдЦреЗрддреЛрдВ рддрдХ рд╕реАрдорд┐рдд рдирд╣реАрдВ рд╣реИред рдХрд▓реНрдкрдирд╛ рдХреАрдЬрд┐рдП рдХрд┐ рд╣рдо рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рд╕реЗ рдкреНрдпрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рдХрд┐ рд╣рдо рдЧрд╛рдпрдм рд╣реИрдВ leftPad
редtype RichString = string & { leftPad: (toLength: number) => string }
рдЗрд╕реЗ рдЬреЛрдбрд╝реЗрдВ String.prototype
ред рдкреНрд░рдХрд╛рд░реЛрдВ рдореЗрдВ рд╡реНрдпрдХреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╕реНрдЯреНрд░рд┐рдВрдЧ рдФрд░ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд▓реЗрддреЗ рд╣реИрдВ рдЬреЛ рдЖрд╡рд╢реНрдпрдХ рдорд╛рди рд▓реЗрддрд╛ рд╣реИред рд╡рд┐рдзрд┐ рдФрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкреНрд░рддрд┐рдЪреНрдЫреЗрджрди рд╣реИрдВредрдПрдХ рд╕рдВрд╕реНрдерд╛
рд╕рдВрдШ - рд╕рдВрдШ - рдЙрдкрдпреЛрдЧреА рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕реАрдПрд╕рдПрд╕ рдореЗрдВ рдПрдХ рддрддреНрд╡ рдХреА рдЪреМрдбрд╝рд╛рдИ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдЪрд░ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП: 10 рдкрд┐рдХреНрд╕рд▓ рдХрд╛ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдпрд╛ рдПрдХ рдирд┐рд░рдкреЗрдХреНрд╖ рдорд╛рдиред CSS рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рд░рд▓рддрд╛ рдХреЗ рд▓рд┐рдП, рдЗрд╕реЗ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдЫреЛрдбрд╝ рджреЗрдВредtype Width = string | number
рдПрдХ рдЙрджрд╛рд╣рд░рдг рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реИред рдорд╛рди рд▓реАрдЬрд┐рдП рд╣рдорд╛рд░рд╛ рдХреЛрдИ рдХрд╛рдо рд╣реИред рдпрд╣ рддреАрди рд░рд╛рдЬреНрдпреЛрдВ рдореЗрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ: рдмрд╕ рдмрдирд╛рдпрд╛, рдХрд╛рдо рдореЗрдВ рд╕реНрд╡реАрдХрд╛рд░ рдХрд┐рдпрд╛ рдФрд░ рдкреВрд░рд╛ рдХрд┐рдпрд╛редtype InitialTask = { id: number, whoCreated: number }
type InWorkTask = { id: number, whoCreated: number }
type FinishTask = { id: number, whoCreated: number, finishDate: Date }
type Task = InitialTask | InWorkTask | FinishedTask
рдкрд╣рд▓реЗ рдФрд░ рджреВрд╕рд░реЗ рд░рд╛рдЬреНрдпреЛрдВ рдореЗрдВ, рдХрд╛рд░реНрдп рдХреЗ рдкрд╛рд╕ рд╣реИ id
рдФрд░ рдЬрд┐рд╕рдиреЗ рдЗрд╕реЗ рдмрдирд╛рдпрд╛ рд╣реИ, рдФрд░ рддреАрд╕рд░реЗ рдореЗрдВ, рдкреВрд░рд╛ рд╣реЛрдиреЗ рдХреА рддрд╛рд░реАрдЦ рджрд┐рдЦрд╛рдИ рджреЗрддреА рд╣реИред рдпрд╣рд╛рдБ рд╕рдВрдШ рдкреНрд░рдХрдЯ рд╣реЛрддрд╛ рд╣реИ - рдпрд╛ рддреЛ рдпрд╣ рдпрд╛ рд╡рд╣редрдзреНрдпрд╛рди рджреЗрдВ ред рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, type
рдЖрдк рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ interface
ред рд▓реЗрдХрд┐рди рдмрд╛рд░реАрдХрд┐рдпрд╛рдВ рд╣реИрдВред рд╕рдВрдШ рдФрд░ рдкреНрд░рддрд┐рдЪреНрдЫреЗрджрди рдХрд╛ рдкрд░рд┐рдгрд╛рдо рд╣рдореЗрд╢рд╛ рдПрдХ рдкреНрд░рдХрд╛рд░ рд╣реЛрддрд╛ рд╣реИред рдЖрдк рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рддрд┐рдЪреНрдЫреЗрджрди рд╡реНрдпрдХреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ extends
, рд▓реЗрдХрд┐рди рд╕рдВрдШ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ interface
рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗред рдпрд╣ type
рд╕рд┐рд░реНрдл рдЫреЛрдЯрд╛ рд╣реИред
interface
рдХреЗрд╡рд▓ рдШреЛрд╖рдгрд╛рдУрдВ рдХреЛ рдорд░реНрдЬ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИред рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдкреНрд░рдХрд╛рд░ рдХреЛ рд╣рдореЗрд╢рд╛ рд╡реНрдпрдХреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ interface
, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рд╕реЗ рдЕрдиреНрдп рдбреЗрд╡рд▓рдкрд░реНрд╕ рдЕрдкрдиреЗ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд╕рд╛рде рдЗрд╕рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░ рд╕рдХреЗрдВрдЧреЗред рдЗрд╕рд▓рд┐рдП рдЯрд╛рдЗрдк рдХрд┐рдпрд╛, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, jQuery- рдкреНрд▓рдЧрдЗрдиреНрд╕редрдЕрдиреБрдХреВрд▓рддрд╛ рдЯрд╛рдЗрдк рдХрд░реЗрдВ
рд▓реЗрдХрд┐рди рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИ - рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ, рд╕рдВрд░рдЪрдирд╛рддреНрдордХ рдкреНрд░рдХрд╛рд░ рдХреА рд╕рдВрдЧрддрддрд╛ рдореЗрдВ ред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рдпрджрд┐ рдкрд╣рд▓реЗ рдФрд░ рджреВрд╕рд░реЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЦреЗрддреЛрдВ рдХрд╛ рдПрдХ рд╣реА рд╕реЗрдЯ рд╣реИ, рддреЛ рдпреЗ рдПрдХ рд╣реА рдкреНрд░рдХрд╛рд░ рдХреЗ рджреЛ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╡рд┐рднрд┐рдиреНрди рдирд╛рдореЛрдВ рдХреЗ рд╕рд╛рде 10 рдкреНрд░рдХрд╛рд░ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдПрдХ рд╕рдорд╛рди рд╕рдВрд░рдЪрдирд╛ (рдПрдХ рд╣реА рдлрд╝реАрд▓реНрдб рдХреЗ рд╕рд╛рде)ред рдпрджрд┐ рд╣рдо 10 рдкреНрд░рдХрд╛рд░реЛрдВ рдореЗрдВ рд╕реЗ рдХреЛрдИ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рдЙрдирдореЗрдВ рд╕реЗ рдХрд┐рд╕реА рдПрдХ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдмреБрд░рд╛ рдирд╣реАрдВ рдорд╛рдиреЗрдЧрд╛редрдЬрд╛рд╡рд╛ рдпрд╛ рд╕реА # рдореЗрдВ, рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд, рдПрдХ рдирд╛рдордорд╛рддреНрд░ рд╕рдВрдЧрддрддрд╛ рдкреНрд░рдгрд╛рд▓реА ред рд╣рдо рд╕рдорд╛рди рдлрд╝реАрд▓реНрдбреНрд╕ рдХреЗ рд╕рд╛рде рд╕рдорд╛рди 10 рдХрдХреНрд╖рд╛рдПрдВ рдФрд░ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦреЗрдВрдЧреЗ рдЬреЛ рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рд▓реЗрддрд╛ рд╣реИред рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдЕрдиреНрдп рд╡рд░реНрдЧреЛрдВ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ рдпрджрд┐ рд╡реЗ рдЙрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рдВрд╢рдЬ рдирд╣реАрдВ рд╣реИрдВ рдЬреЛ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рд╣реИредрд╕рдВрд░рдЪрдирд╛рддреНрдордХ рд╕рдВрдЧрддрддрд╛ рд╕рдорд╕реНрдпрд╛ рдХреЛ рдлрд╝реАрд▓реНрдб рдореЗрдВ рд╕реНрдерд┐рддрд┐ рдЬреЛрдбрд╝рдХрд░ рд╕рдВрдмреЛрдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ: enum
рдпрд╛string
ред рд▓реЗрдХрд┐рди рдпреЛрдЧ рдкреНрд░рдХрд╛рд░ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдП рдЬрд╛рдиреЗ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рд╢рдмреНрджрд╛рд░реНрде рдХреЛ рд╡реНрдпрдХреНрдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рд╣реИредрдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рд╣рдо ReasonML рдХреЛ рд╕рдВрдмреЛрдзрд┐рдд рдХрд░реЗрдВрдЧреЗред рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдпрд╣ рд╡рд╣рд╛рдВ рджрд┐рдЦрддрд╛ рд╣реИредtype Task =
| Initial({ id: int, whoCreated: int })
| InWork({ id: int, whoCreated: int })
| Finished({
id: int,
whoCreated: int,
finshDate: Date
})
рдПрдХ рд╣реА рдХреНрд╖реЗрддреНрд░реЛрдВ, рд╕рд┐рд╡рд╛рдп рдЗрд╕рдХреЗ рдХрд┐ int
рдмрдЬрд╛рдп number
ред рдпрджрд┐ рдЖрдк рдмрд╛рд░реАрдХреА рд╕реЗ рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдзреНрдпрд╛рди рджреЗрдВ Initial
, InWork
рдФрд░ Finished
ред рд╡реЗ рдмрд╛рдИрдВ рдУрд░ рд╕реНрдерд┐рдд рдирд╣реАрдВ рд╣реИрдВ, рдЯрд╛рдЗрдк рдирд╛рдо рдореЗрдВ, рд▓реЗрдХрд┐рди рдкрд░рд┐рднрд╛рд╖рд╛ рдореЗрдВ рджрд╛рдИрдВ рдУрд░ред рдпрд╣ рдХреЗрд╡рд▓ рд╢реАрд░реНрд╖рдХ рдореЗрдВ рдПрдХ рдкрдВрдХреНрддрд┐ рдирд╣реАрдВ рд╣реИ, рдмрд▓реНрдХрд┐ рдПрдХ рдЕрд▓рдЧ рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдкрд╣рд▓реЗ рдХреЛ рджреВрд╕рд░реЗ рд╕реЗ рдЕрд▓рдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВредрдЬреАрд╡рди рд╣реИрдХ ред рдЬреЗрдиреЗрд░рд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП (рдЬреИрд╕реЗ рдЖрдкрдХреА рдбреЛрдореЗрди рдЗрдХрд╛рдЗрдпрд╛рдБ) рдПрдХ рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдБ global.d.ts
рдФрд░ рдЙрд╕рдореЗрдВ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдЬреЛрдбрд╝реЗрдВред рд╡реЗ рд╕реНрдкрд╖реНрдЯ рдЖрдпрд╛рдд рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рдмрд┐рдирд╛ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛрдбрдмреЗрд╕ рдореЗрдВ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рджрд┐рдЦрд╛рдИ рджреЗрдВрдЧреЗред рдпрд╣ рдорд╛рдЗрдЧреНрд░реЗрд╢рди рдХреЗ рд▓рд┐рдП рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЖрдкрдХреЛ рдпрд╣ рдЪрд┐рдВрддрд╛ рдХрд░рдиреЗ рдХреА рдЬрд╝рд░реВрд░рдд рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЯрд╛рдЗрдк рдХрд╣рд╛рдВ рд░рдЦреЗрдВредрдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдХрд░рдирд╛ рд╣реИ, рдЖрджрд┐рдо Redux рдХреЛрдб рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛редexport const taskReducer = (state, action) = > {
switch (action.type) {
case "TASK_FETCH":
return { isFetching: true }
case "TASK_SUCCESS":
return { isFetching: false, task: action.payload }
case "TASK_FAIL":
return { isFetching: false, erro: action.payload }
}
return state
}
рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдХреЛрдб рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦреЗрдВред рдЪрд▓реЛ рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдирд╛рдо рдмрджрд▓рдХрд░ - рд╕реЗ рд╢реБрд░реВ .js
рдХрд░рддреЗ рд╣реИрдВ .ts
ред рд╕рднреА рд░рд╛рдЬреНрдп рд╡рд┐рдХрд▓реНрдкреЛрдВ рдФрд░ noImplicitAny рд╡рд┐рдХрд▓реНрдк рдХреЛ рдЪрд╛рд▓реВ рдХрд░реЗрдВред рдпрд╣ рд╡рд┐рдХрд▓реНрдк рдЙрди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдвреВрдВрдврддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдкреИрд░рд╛рдореАрдЯрд░ рдкреНрд░рдХрд╛рд░ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдирд╣реАрдВ рд╣реИ, рдФрд░ рдкреНрд░рд╡рд╛рд╕ рдХреЗ рдЪрд░рдг рдореЗрдВ рдЙрдкрдпреЛрдЧреА рд╣реИредрд╡рд┐рд╢рд┐рд╖реНрдЯ State
: рдлрд╝реАрд▓реНрдб рдЬреЛрдбрд╝реЗрдВ isFetching
, Task
(рдЬреЛ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛) рдФрд░ Error
редtype Task = { title: string }
declare module "*.jpg" {
const url: string
export default url
}
declare module "*.png" {
const url: string
export default url
}
рдзреНрдпрд╛рди рджреЗрдВред рд▓рд╛рдЗрдлрд╣реЙрдХ рдиреЗ рдмрд╕рд░рдд рдЕрд▓реА рд╕реИрдпрдж рдХреЗ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдбреАрдк рдбрд╛рдЗрд╡ рдореЗрдВ рдЭрд╛рдБрдХрд╛ ред рдпрд╣ рдереЛрдбрд╝рд╛ рджрд┐рдирд╛рдВрдХрд┐рдд рд╣реИ, рд▓реЗрдХрд┐рди рдлрд┐рд░ рднреА рдЙрди рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реИ рдЬреЛ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдЧреЛрддрд╛ рд▓рдЧрд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред Marius Schulz рдХреЗ рдмреНрд▓реЙрдЧ рдкрд░ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреА рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрдврд╝реЗрдВ ред рд╡рд╣ рдирдИ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдФрд░ рдЯреНрд░рд┐рдХреНрд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд▓рд┐рдЦрддреЗ рд╣реИрдВред рдкрд░рд┐рд╡рд░реНрддрди рд▓реЙрдЧ рдХрд╛ рднреА рдЕрдзреНрдпрдпрди рдХрд░реЗрдВ, рдЕрдкрдбреЗрдЯ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рди рдХреЗрд╡рд▓ рдЬрд╛рдирдХрд╛рд░реА рд╣реИ, рдмрд▓реНрдХрд┐ рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд░реЗрдВредрдХреА рдЧрдИ рдХрд╛рд░реНрдпрд╡рд╛рд╣реАред рд╣рдо рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЛ рдЯрд╛рдЗрдк рдФрд░ рдШреЛрд╖рд┐рдд рдХрд░реЗрдВрдЧреЗредtype FetchAction = {
type: "TASK_FETCH"
}
type SuccessAction = {
type: "TASK_SUCCESS",
payload: Task
type FailAction = {
type: "TASK_FAIL",
payload: Error
}
type Actions = FetchAction | SuccessAction | FailAction
type
рд╕рднреА рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдлрд╝реАрд▓реНрдб рдЕрд▓рдЧ рд╣реИ, рдпрд╣ рд╕рд┐рд░реНрдл рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдирд╣реАрдВ рд╣реИ, рдмрд▓реНрдХрд┐ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реИ - рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ ред рдпрд╣ рдмрд╣реБрдд рд╣реА рднреЗрджрднрд╛рд╡рдкреВрд░реНрдг рд╣реИ - рд╡рд╣ рдЯреИрдЧ рдЬрд┐рд╕рдХреЗ рджреНрд╡рд╛рд░рд╛ рд╣рдо рд╕рднреА рдорд╛рдорд▓реЛрдВ рдХреЛ рдЕрд▓рдЧ рдХрд░рддреЗ рд╣реИрдВред рд╣рдореЗрдВ рдПрдХ рднреЗрджрднрд╛рд╡рдкреВрд░реНрдг рд╕рдВрдШ рдорд┐рд▓рд╛ рдФрд░ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо рд╕рдордЭ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдкреЗрд▓реЛрдб рдореЗрдВ рдХреНрдпрд╛ рд╣реИредрдореВрд▓ Redux рдХреЛрдб рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВ:export const taskReducer = (state: State, action: Actions): State = > {
switch (action.type) {
case "TASK_FETCH":
return { isFetching: true }
case "TASK_SUCCESS":
return { isFetching: false, task: action.payload }
case "TASK_FAIL":
return { isFetching: false, error: action.payload }
}
return state
}
рдЕрдЧрд░ рд╣рдо рд▓рд┐рдЦрддреЗ рд╣реИрдВ рддреЛ рдпрд╣рд╛рдБ рдЦрддрд░рд╛ рд╣реИ string
...type FetchAction = {
type: string
}
... рддреЛ рд╕рдм рдХреБрдЫ рдЯреВрдЯ рдЬрд╛рдПрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЕрдм рдХреЛрдИ рднреЗрджрднрд╛рд╡ рдирд╣реАрдВ рд╣реИредрдЗрд╕ рдХреНрд░рд┐рдпрд╛ рдореЗрдВ, рдЯрд╛рдЗрдк рдХреЛрдИ рднреА рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реЛ рд╕рдХрддреА рд╣реИ, рдФрд░ рд╡рд┐рд╢рд┐рд╖реНрдЯ рднреЗрджрднрд╛рд╡ рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдирд╣реАрдВред рдЙрд╕рдХреЗ рдмрд╛рдж, рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдПрдХ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреЛ рджреВрд╕рд░реЗ рд╕реЗ рдЕрд▓рдЧ рдХрд░рдиреЗ рдФрд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдЦреЛрдЬрдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рдЗрд╕рд▓рд┐рдП, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╢рд╛рдмреНрджрд┐рдХ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдо рдЗрд╕ рдбрд┐рдЬрд╛рдЗрди рдХреЛ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ type ActionType = Actions["type"]
:редрд╣рдорд╛рд░реЗ рддреАрди рд╡рд┐рдХрд▓реНрдк рд╕рдВрдХреЗрддреЛрдВ рдореЗрдВ рдкреЙрдк рдЕрдк рд╣реЛрдВрдЧреЗред
рдпрджрд┐ рдЖрдк рд▓рд┐рдЦрддреЗ рд╣реИрдВ ...type FetchAction = {
type: string
}
... рддреЛ рд╕рдВрдХреЗрдд рд╕рд░рд▓ рд╣реЛрдВрдЧреЗ string
, рдХреНрдпреЛрдВрдХрд┐ рдЕрдиреНрдп рд╕рднреА рд▓рд╛рдЗрдиреЗрдВ рдЕрдм рдорд╣рддреНрд╡рдкреВрд░реНрдг рдирд╣реАрдВ рд╣реИрдВред
рд╣рдордиреЗ рд╕рднреА рдЯрд╛рдЗрдк рдХрд┐рдП рд╣реИрдВ рдФрд░ рд░рд╛рд╢рд┐ рдХрд╛ рдкреНрд░рдХрд╛рд░ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рд╣реИредрдердХрд╛ рджреЗрдиреЗ рд╡рд╛рд▓реА рдЬрд╛рдБрдЪ
рдПрдХ рдХрд╛рд▓реНрдкрдирд┐рдХ рд╕реНрдерд┐рддрд┐ рдХреА рдХрд▓реНрдкрдирд╛ рдХрд░реЗрдВ рдЬрд╣рд╛рдВ рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдХреЛрдб рдореЗрдВ рдирд╣реАрдВ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИредexport const taskReducer = (state: State, action: Actions): State = > {
switch (action.type) {
case "TASK_FETCH":
return { isFetching: true }
case "TASK_SUCCESS":
return { isFetching: false, task: action.payload }
}
return state
}
рдпрд╣рд╛рдБ рд╕рдВрдкреВрд░реНрдг рдЬрд╛рдБрдЪ рд╕реЗ рд╣рдореЗрдВ рдорджрдж рдорд┐рд▓реЗрдЧреА - рдПрдХ рдФрд░ рдЙрдкрдпреЛрдЧреА рд╕рдВрдкрддреНрддрд┐ рдЬреИрд╕реЗ рдХрд┐ рд░рд╛рд╢рд┐ ред рдпрд╣ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдЕрд╡рд╕рд░ рд╣реИ рдХрд┐ рд╣рдордиреЗ рд╕рднреА рд╕рдВрднрд╛рд╡рд┐рдд рдорд╛рдорд▓реЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░ рд▓рд┐рдпрд╛ рд╣реИредрд╕реНрд╡рд┐рдЪ рд╕реНрдЯреЗрдЯрдореЗрдВрдЯ рдХреЗ рдмрд╛рдж рдПрдХ рд╡реИрд░рд┐рдПрдмрд▓ рдЬреЛрдбрд╝реЗрдВ const exhaustiveCheck: never = action
:редрдХрднреА рднреА рдПрдХ рджрд┐рд▓рдЪрд╕реНрдк рдкреНрд░рдХрд╛рд░ рдирд╣реАрдВ рд╣реИ:- рдпрджрд┐ рдпрд╣ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд░рд┐рдЯрд░реНрди рдХрд╛ рдкрд░рд┐рдгрд╛рдо рд╣реИ, рддреЛ рдлрд╝рдВрдХреНрд╢рди рдХрднреА рднреА рд╕рд╣реА рдврдВрдЧ рд╕реЗ рд╕рдорд╛рдкреНрдд рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╣ рд╣рдореЗрд╢рд╛ рдПрдХ рддреНрд░реБрдЯрд┐ рдлреЗрдВрдХрддрд╛ рд╣реИ рдпрд╛ рдмрд┐рдирд╛ рдХрд┐рд╕реА рддреНрд░реБрдЯрд┐ рдХреЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрддрд╛ рд╣реИ);
- рдпрджрд┐ рдпрд╣ рдПрдХ рдкреНрд░рдХрд╛рд░ рд╣реИ, рддреЛ рдпрд╣ рдкреНрд░рдХрд╛рд░ рдмрд┐рдирд╛ рдХрд┐рд╕реА рдЕрддрд┐рд░рд┐рдХреНрдд рдкреНрд░рдпрд╛рд╕ рдХреЗ рдирд╣реАрдВ рдмрдирд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдЕрдм рд╕рдВрдХрд▓рдХ рддреНрд░реБрдЯрд┐ рдХрд╛ рд╕рдВрдХреЗрдд рджреЗрдЧрд╛ "рдЯрд╛рдЗрдк 'рдлреЗрд▓ рдПрдХреНрд╢рди' 'рдХрднреА рдирд╣реАрдВ" рдЯрд╛рдЗрдк рдХрд░рдиреЗ рдпреЛрдЧреНрдп рдирд╣реАрдВ рд╣реИред рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рддреАрди рд╕рдВрднрд╛рд╡рд┐рдд рдкреНрд░рдХрд╛рд░ рдХреЗ рдХрд╛рд░реНрдп рд╣реИрдВ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рд╣рдордиреЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ "TASK_FAIL"
- рдпрд╣ рд╣реИ FailAction
ред рд▓реЗрдХрд┐рди рдХрднреА рдирд╣реАрдВ, рдпрд╣ "рдЕрд╕рд╛рдЗрди рдХрд░рдиреЗ рдпреЛрдЧреНрдп" рдирд╣реАрдВ рд╣реИредрдЖрдЗрдП рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдЬреЛрдбрд╝реЗрдВ "TASK_FAIL"
, рдФрд░ рдХреЛрдИ рдФрд░ рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рд╣реЛрдЧреАред рд╕рдВрд╕рд╛рдзрд┐рдд "TASK_FETCH"
- рд▓реМрдЯрд╛рдпрд╛ рдЧрдпрд╛, рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ "TASK_SUCCESS"
- рд▓реМрдЯрд╛рдпрд╛ рдЧрдпрд╛, рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ "TASK_FAIL"
ред рдЬрдм рд╣рдордиреЗ рд╕рднреА рддреАрди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛, рддреЛ рдХреНрдпрд╛ рдХрд╛рд░реНрд░рд╡рд╛рдИ рд╣реЛ рд╕рдХрддреА рд╣реИ? рдХреБрдЫ рдирд╣реАрдВ - never
редрдпрджрд┐ рдЖрдк рдПрдХ рдФрд░ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рддреЛ рд╕рдВрдХрд▓рдХ рдЖрдкрдХреЛ рдмрддрд╛рдПрдЧрд╛ рдХрд┐ рдХреМрди рд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдирд╣реАрдВ рд╣реИрдВред рдпрд╣ рдорджрдж рдХрд░реЗрдЧрд╛ рдпрджрд┐ рдЖрдк рд╕рднреА рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдЬрд╡рд╛рдм рджреЗрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдФрд░ рдпрджрд┐ рдХреЗрд╡рд▓ рдЪрдпрдирд╛рддреНрдордХ рд╣реИ, рддреЛ рдирд╣реАрдВредрдкрд╣рд▓реА рдЯрд┐рдк
рдХрдард┐рди рдкреНрд░рдпрд╛рд╕ред
рдкрд╣рд▓реЗ рддреЛ рдпрд╣ рдЧреЛрддрд╛ рд▓рдЧрд╛рдирд╛ рдХрдард┐рди рд╣реЛрдЧрд╛: рдпреЛрдЧ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрдврд╝реЗрдВ, рдлрд┐рд░ рдЙрддреНрдкрд╛рджреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ, рдмреАрдЬреАрдп рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░, рдФрд░ рдЗрд╕реА рддрд░рд╣ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдореЗрдВред рдПрдХ рдкреНрд░рдпрд╛рд╕ рдХрд░рдирд╛ рд╣реЛрдЧрд╛редрдЬрдм рд╣рдо рдЧрд╣рд░рд╛ рдЧреЛрддрд╛ рд▓рдЧрд╛рддреЗ рд╣реИрдВ, рддреЛ рд╣рдорд╛рд░реЗ рдКрдкрд░ рдкрд╛рдиреА рдХреЗ рд╕реНрддрдВрдн рдХрд╛ рджрдмрд╛рд╡ рдмрдврд╝ рдЬрд╛рддрд╛ рд╣реИред рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдЧрд╣рд░рд╛рдИ рдкрд░, рд╣рдорд╛рд░реЗ рдКрдкрд░ рдХрд╛ рдЙрдЫрд╛рд▓ рдмрд▓ рдФрд░ рдкрд╛рдиреА рдХрд╛ рджрдмрд╛рд╡ рд╕рдВрддреБрд▓рд┐рдд рд╣реЛрддрд╛ рд╣реИред рдпрд╣ "рддрдЯрд╕реНрде рдЙрдЫрд╛рд▓" рдХрд╛ рдПрдХ рдХреНрд╖реЗрддреНрд░ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╣рдо рднрд╛рд░рд╣реАрдирддрд╛ рдХреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╣реИрдВред рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рд╣рдо рдЕрдиреНрдп рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд┐рд╕реНрдЯрдо рдпрд╛ рднрд╛рд╖рд╛рдУрдВ рдХреА рдУрд░ рдореБрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВредрдирд╛рдордорд╛рддреНрд░ рдкреНрд░рдХрд╛рд░ рдХреА рдкреНрд░рдгрд╛рд▓реА
рдкреНрд░рд╛рдЪреАрди рд░реЛрдо рдореЗрдВ, рдирд┐рд╡рд╛рд╕рд┐рдпреЛрдВ рдХреЗ рдирд╛рдо рдХреЗ рддреАрди рдШрдЯрдХ рдереЗ: рдЙрдкрдирд╛рдо, рдирд╛рдо рдФрд░ "рдЙрдкрдирд╛рдо"ред рдирд╛рдо рд╣реА рд╣реИ "рдирд╛рдорд░реНрджред" рдЗрд╕рд╕реЗ рдирд╛рдордорд╛рддреНрд░ рдкреНрд░рдХрд╛рд░ рдХреА рдкреНрд░рдгрд╛рд▓реА рдЖрддреА рд╣реИ - "рдирд╛рдордорд╛рддреНрд░"ред рдпрд╣ рдХрднреА-рдХрднреА рдЙрдкрдпреЛрдЧреА рд╣реЛрддрд╛ рд╣реИредрдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдРрд╕рд╛ рдлрд╝рдВрдХреНрд╢рди рдХреЛрдб рд╣реИредexport const githubUrl = process.env.GITHUB_URL as string
export const nodeEnv = process.env.NODE_ENV as string
export const fetchStarredRepos = (
nodeEnv: string,
githubUrl: string
): Promise<GithubRepo[ ]> => {
if (nodeEnv = "production") {
}
return fetch('$githubUrl}/users/saitonakamura/starred')
.then(r => r.json());
}
рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди API рдкрд░ рдЖрддрд╛ рд╣реИ GITHUB_URL=https://api.github.com
:ред githubUrl
рдПрдкреАрдЖрдИ рд╡рд┐рдзрд┐ рдЙрди рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХреЛ рдмрд╛рд╣рд░ рдирд┐рдХрд╛рд▓рддреА рд╣реИ рдЬрд┐рди рдкрд░ рд╣рдо рдПрдХ рддрд╛рд░рд╛рдВрдХрди рдЪрд┐рд╣реНрди рд▓рдЧрд╛рддреЗ рд╣реИрдВред рдФрд░ рдЕрдЧрд░ nodeEnv = "production"
, рддреЛ рдпрд╣ рдХреЙрд▓ рд▓реЙрдЧ рдХрд░рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдореИрдЯреНрд░рд┐рдХреНрд╕ рдХреЗ рд▓рд┐рдПредрдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рд╣рдо (UI) рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВредimport React, { useState } from "react"
export const StarredRepos = () => {
const [starredRepos, setStarredRepos] = useState<GithubRepo[ ] | null>(null)
if (!starredRepos) return <div>LoadingтАж</div>
return (
<ul>
{starredRepos.map(repo => (
<li key={repo.name}>repo.name}</li>
))}
</ul>
)
}
type GithubRepo = {
name: string
}
рдлрд╝рдВрдХреНрд╢рди рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рдбреЗрдЯрд╛ рдХреИрд╕реЗ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдП, рдФрд░ рдпрджрд┐ рдХреЛрдИ рдирд╣реАрдВ рд╣реИ, рддреЛ рдПрдХ рд▓реЛрдбрд░ред рдпрд╣ рдПрдкреАрдЖрдИ рдХреЙрд▓ рдЬреЛрдбрд╝рдиреЗ рдФрд░ рдбреЗрдЯрд╛ рдХреЛ рдЖрдмрд╛рдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛ рд╣реБрдЖ рд╣реИредuseEffect(() => {
fetchStarredRepos(githubUrl, nodeEnv).then(data => setStarredRepos(data))
}, [ ])
рд▓реЗрдХрд┐рди рдЕрдЧрд░ рд╣рдо рдЗрд╕ рдХреЛрдб рдХреЛ рдЪрд▓рд╛рддреЗ рд╣реИрдВ, рддреЛ рд╕рдм рдХреБрдЫ рдЧрд┐рд░ рдЬрд╛рдПрдЧрд╛ред рдбреЗрд╡рд▓рдкрд░ рдкреИрдирд▓ рдореЗрдВ, рд╣рдо рдкрд╛рддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ fetch
рдкрддреЗ рддрдХ рдкрд╣реБрдВрдЪ рд░рд╣рд╛ рд╣реИ '/users/saitonakamura/starred'
- githubUrl рдХрд╣реАрдВ рдЧрд╛рдпрдм рд╣реЛ рдЧрдпрд╛ рд╣реИред рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рд╕рднреА рдЕрдЬреАрдм рдбрд┐рдЬрд╛рдЗрди рдХреЗ рдХрд╛рд░рдг - nodeEnv
рдкрд╣рд▓реЗ рдЖрддрд╛ рд╣реИред рдмреЗрд╢рдХ, рдпрд╣ рд╕рдм рдХреБрдЫ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдХрд░реНрд╖рдХ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреЛрдб рдЖрдзрд╛рд░ рдореЗрдВ рдЕрдиреНрдп рд╕реНрдерд╛рдиреЛрдВ рдкрд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИредрд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рдХрдВрдкрд╛рдЗрд▓рд░ рдЗрд╕реЗ рдкрд╣рд▓реЗ рд╕реЗ рдкреНрд░реЙрдорд┐рд╕ рдХрд░реЗ? рдлрд┐рд░ рдЖрдкрдХреЛ рд╕рдВрдкреВрд░реНрдг рд▓реЙрдиреНрдЪ рдЪрдХреНрд░ рд╕реЗ рдЧреБрдЬрд░рдирд╛ рд╣реЛрдЧрд╛, рдПрдХ рддреНрд░реБрдЯрд┐ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдирд╛ рд╣реЛрдЧрд╛ рдпрд╛ рдХрд╛рд░рдгреЛрдВ рдХреА рдЦреЛрдЬ рдХрд░рдиреА рд╣реЛрдЧреАредрдмреНрд░рд╛рдВрдбрд┐рдВрдЧ
рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рд╣реИрдХ рд╣реИ - рдмреНрд░рд╛рдВрдб рдкреНрд░рдХрд╛рд░ред рдмрдирд╛рдПрдБ Brand
, B
(рд╕реНрдЯреНрд░рд┐рдВрдЧ), T
рдФрд░ рджреЛ рдкреНрд░рдХрд╛рд░ред рд╣рдо рдЙрд╕реА рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП рдмрдирд╛рдПрдВрдЧреЗ NodeEnv
редtype Brand<T, B extends string> = T & { readonly _brand: B }
type GithubUrl = Brand<string, "githubUrl">
export const githubUrl = process.env.GITHUB_URL as GithubUrl
type NodeEnv = Brand<string, "nodeEnv">
export const nodeEnv = process.env.NODE_ENV as NodeEnv
рд▓реЗрдХрд┐рди рд╣рдореЗрдВ рдПрдХ рддреНрд░реБрдЯрд┐ рдорд┐рд▓рддреА рд╣реИред
рдЕрдм githubUrl
рдпрд╣ рд╣реИ nodeEnv
, рдПрдХ рджреВрд╕рд░реЗ рдХреЛ рдЖрд╡рдВрдЯрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрд╕рдВрднрд╡ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЗрди рдирд╛рдордорд╛рддреНрд░ рдкреНрд░рдХрд╛рд░ рд╣реИрдВред рд╡рд┐рдиреАрдд, рд▓реЗрдХрд┐рди рдирд╛рдордорд╛рддреНрд░ рдХрд╛ред рдЕрдм рд╣рдо рдЙрдиреНрд╣реЗрдВ рдпрд╣рд╛рдБ рд╕реНрд╡реИрдк рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ - рд╣рдо рдЙрдиреНрд╣реЗрдВ рдХреЛрдб рдХреЗ рджреВрд╕рд░реЗ рднрд╛рдЧ рдореЗрдВ рдмрджрд▓рддреЗ рд╣реИрдВредuseEffect(() => {
fetchStarresRepos(nodeEnv, githubUrl).then(data => setStarredRepos(data))
}, [ ])
рдЕрдм рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реИ - рдЙрдиреНрд╣реЗрдВ рдмреНрд░рд╛рдВрдбреЗрдб рдкреНрд░рд┐рдорд┐рдЯрд┐рд╡ рдорд┐рд▓рд╛ ред рдХрдИ рддрд░реНрдХреЛрдВ (рддрд╛рд░реЛрдВ, рд╕рдВрдЦреНрдпрд╛рдУрдВ) рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдиреЗ рдкрд░ рдмреНрд░рд╛рдВрдбрд┐рдВрдЧ рдЙрдкрдпреЛрдЧреА рд╣реЛрддреА рд╣реИред рдЙрдирдХреЗ рдкрд╛рд╕ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╢рдмреНрджрд╛рд░реНрде рд╣реИ (x, y рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ), рдФрд░ рдЙрдиреНрд╣реЗрдВ рднреНрд░рдорд┐рдд рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ рдЬрдм рдХрдВрдкрд╛рдЗрд▓рд░ рдЖрдкрдХреЛ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рд╡реЗ рднреНрд░рдорд┐рдд рд╣реИрдВредрд▓реЗрдХрд┐рди рджреЛ рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реИрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдореВрд▓ рдирд╛рдордорд╛рддреНрд░ рдкреНрд░рдХрд╛рд░ рдирд╣реАрдВ рд╣реЛрддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЗрд╕реЗ рд╕реБрд▓рдЭрд╛ рд▓рд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЗрд╕ рдореБрджреНрджреЗ рдХреА рдПрдХ рдЪрд░реНрдЪрд╛ рднрд╛рд╖рд╛ рднрдВрдбрд╛рд░ рдореЗрдВ рдЪрд▓ рд░рд╣реА рд╣реИ редрджреВрд╕рд░реА рд╕рдорд╕реНрдпрд╛ "рдХреЗ рд░реВрдк рдореЗрдВ" рд╣реИ, рдХреЛрдИ рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рд╣реИ рдХрд┐ GITHUB_URL
рд▓рд┐рдВрдХ рдЯреВрдЯрд╛ рдирд╣реАрдВ рд╣реИредрд╕рд╛рде рд╣реА рд╕рд╛рде NODE_ENV
ред рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ, рд╣рдо рди рдХреЗрд╡рд▓ рдХреБрдЫ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди "production"
рдпрд╛ "development"
редtype NodeEnv = Brand<"production" | "development" | "nodeEnv">
export const nodeEnv = process.env.NODE_ENV as NodeEnv
рдпрд╣ рд╕рдм рдЬрд╛рдБрдЪрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдореИрдВ рдЖрдкрдХреЛ рд╕реНрдорд╛рд░реНрдЯ рдбрд┐рдЬрд╛рдЗрдирд░реЛрдВ рдФрд░ рд╕рд░реНрдЧреЗрдИ рдЪреЗрд░реЗрдкреЛрдиреЛрд╡ рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХрд╛ рдЙрд▓реНрд▓реЗрдЦ рдХрд░ рд░рд╣рд╛ рд╣реВрдВ, " рдПрдХ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╢реИрд▓реА рдореЗрдВ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рд╕рд╛рде рдПрдХ рдбреЛрдореЗрди рдбрд┐рдЬрд╛рдЗрди рдХрд░рдирд╛ ред"рджреВрд╕рд░рд╛ рдФрд░ рддреАрд╕рд░рд╛ рдЯрд┐рдкреНрд╕
рд╕рд╛рд╡рдзрд╛рди рд░рд╣реЗрдВред
рдХрднреА-рдХрднреА рд░реБрдХреЗрдВ рдФрд░ рдЪрд╛рд░реЛрдВ рдУрд░ рджреЗрдЦреЗрдВ: рдЕрдиреНрдп рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ, рдЪреМрдЦрдЯреЗ, рдЯрд╛рдЗрдк рд╕рд┐рд╕реНрдЯрдоред рдирдП рд╕рд┐рджреНрдзрд╛рдВрдд рд╕реАрдЦреЗрдВ рдФрд░ рд╕рдмрдХ рд╕реАрдЦреЗрдВредрдЬрдм рд╣рдо "рддрдЯрд╕реНрде рдЙрдЫрд╛рд▓" рдХреЗ рдмрд┐рдВрджреБ рдХреЛ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдкрд╛рдиреА рдХрдард┐рди рд░реВрдк рд╕реЗ рджрдмрд╛рддрд╛ рд╣реИ рдФрд░ рд╣рдореЗрдВ рдиреАрдЪреЗ рдЦреАрдВрдЪрддрд╛ рд╣реИредрдЖрд░рд╛рдо рдХрд░реЗрдВред
рдЧрд╣рд░рд╛ рдЧреЛрддрд╛ рд▓рдЧрд╛рдПрдБ рдФрд░ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рдЕрдкрдирд╛ рдХрд╛рдо рдХрд░рдиреЗ рджреЗрдВредрдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреНрдпрд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реИ
рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЯрд╛рдЗрдк рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ редexport const createFetch = () => ({
type: "TASK_FETCH"
})
export const createSuccess = (task: Task) => ({
type: "TASK_SUCCESS"
payload: Task
})
export const createFail = (error: Error) => ({
type: "TASK_FAIL"
payload: error
})
type FetchAction = {
type: "TASK_FETCH",
type SuccessAction = {
type: "TASK_SUCCESS",
payload: Task
type FailAction = {
type: "TASK_FAIL",
payload: Error
}
рдЗрд╕рдХреЗ рд▓рд┐рдП рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╣реИ ReturnType
- рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рд╕реЗ рд░рд┐рдЯрд░реНрди рд╡реИрд▓реНрдпреВ рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ:type FetchAction = ReturnType<typeof createFetch>
рдЗрд╕рдореЗрдВ рд╣рдо рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рдХреЗрд╡рд▓ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдирд╣реАрдВ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ: рдлрд╝рдВрдХреНрд╢рди рдпрд╛ рд╡реЗрд░рд┐рдПрдмрд▓ рд╕реЗ рдПрдХ рдкреНрд░рдХрд╛рд░ рд▓реЗрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛ typeof
редрд╣рдо рдпреБрдХреНрддрд┐рдпреЛрдВ рдореЗрдВ рджреЗрдЦрддреЗ рд╣реИрдВ type: string
ред
рдпрд╣ рдмреБрд░рд╛ рд╣реИ - рднреЗрджрднрд╛рд╡ рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдЯреВрдЯ рдЬрд╛рдПрдЧрд╛ рдХреНрдпреЛрдВрдХрд┐ рдПрдХ рд╡рд╕реНрддреБ рд╢рд╛рдмреНрджрд┐рдХ рд╣реИредexport const createFetch = () => ({
type: "TASK_FETCH"
})
рдЬрдм рд╣рдо рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдкрд░рд┐рд╡рд░реНрддрдирд╢реАрд▓ рд╣реЛрддрд╛ рд╣реИред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рдПрдХ рдХреНрд╖реЗрддреНрд░ рдФрд░ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд╕рд╛рде, рд╣рдо рдмрд╛рдж рдореЗрдВ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рджреВрд╕рд░реЗ рдореЗрдВ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореНрдпреВрдЯреЗрдмрд▓ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдмрдврд╝рд╛рддрд╛ рд╣реИредрд╣рдореЗрдВ рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреА рдорджрдж рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рд▓рд┐рдП рдХреЙрдиреНрд╕реНрдЯреЗрдмрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рд╣реИредexport const createFetch = ( ) => ({
type: "TASK_FETCH" as const
})
рдЬреЛрдбрд╝реЗрдВ - рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕рдВрдХреЗрддреЛрдВ рдореЗрдВ рддреБрд░рдВрдд рдЧрд╛рдпрдм рд╣реЛ рдЬрд╛рдПрдЧреАред рд╣рдо рдЗрд╕реЗ рдХреЗрд╡рд▓ рд░реЗрдЦрд╛ рдХреЗ рдкрд╛рд░ рд╣реА рдирд╣реАрдВ, рдмрд▓реНрдХрд┐ рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рдкреВрд░реЗ рд╢рд╛рдмреНрджрд┐рдХ рд░реВрдк рдореЗрдВ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВредexport const createFetch = ( ) => ({
type: "TASK_FETCH"
} as const)
рдлрд┐рд░ рдЯрд╛рдЗрдк (рдФрд░ рд╕рднреА рдлрд╝реАрд▓реНрдб) рдЖрд╕рд╛рдиреА рд╕реЗ рд╣реЛ рдЬрд╛рдПрдВрдЧреЗредtype FetchAction = {
readonly type: "TASK_FETCH";
}
рдпрд╣ рдЙрдкрдпреЛрдЧреА рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдЖрдк рдЕрдкрдиреА рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреА рдкрд░рд┐рд╡рд░реНрддрдирд╢реАрд▓рддрд╛ рдХреЛ рдмрджрд▓рдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдирд╣реАрдВ рд╣реИред рдЗрд╕рд▓рд┐рдП, рд╣рдо рд╣рд░ рдЬрдЧрд╣ рдХрд╛рд╕реНрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВредexport const createFetch = () => ({
type: "TASK_FETCH"
} as const)
export const createSuccess = (task: Task) => ({
type: "TASK_SUCCESS"
payload: Task
} as const)
export const createFail = (error: Error) => ({
type: "TASK_FAIL"
payload: error
} as const)
type Actions =
| ReturnType<typeof createFetch>
| ReturnType<typeof createSuccess>
| ReturnType<typeof createFail>
type State =
| { isFetching: true }
| { isFetching: false; task: Task }
| { isFetching: false; error: Error }
export const taskReducer = (state: State, action: Actions): State = > {
switch (action.type) {
case "TASK_FETCH":
return { isFetching: true }
case "TASK_SUCCESS":
return { isFetching: false, task: action.payload }
case "TASK_FAIL":
return { isFetching: false, error: action.payload }
}
const _exhaustiveCheck: never = action
return state
}
рдХреЛрдб рдЯрд╛рдЗрдк рдХрд░рдиреЗ рд╡рд╛рд▓реА рд╕рднреА рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рдХрдо рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдХреЙрдиреНрд╕реНрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИред рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдиреЗ рдмрд╛рдХреА рд╕рдм рдХреБрдЫ рд╕рдордЭрд╛редрдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╕реНрдЯреЗрдЯ рдЖрдЙрдЯрдкреБрдЯ рдХрд░ рд╕рдХрддрд╛ рд╣реИ ред рдпрд╣ рд╕рдВрдШ рдХреЗ рддреАрди рд╕рдВрднрд╛рд╡рд┐рдд рд░рд╛рдЬреНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб рдореЗрдВ рд╕рдВрдШ рджреНрд╡рд╛рд░рд╛ рджрд░реНрд╢рд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ: рд╕рд╣реА, рдЧрд▓рдд, рдпрд╛ рдХрд╛рд░реНрдп:редрд╕реНрдЯреЗрдЯ = рд░рд┐рдЯрд░реНрди рдЯрд╛рдЗрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╕рдВрдХреЗрдд рдЗрдВрдЧрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдПрдХ рдкрд░рд┐рдкрддреНрд░ рдирд┐рд░реНрднрд░рддрд╛ рд╣реИред
рдЫреЛрдЯрд╛редtype State = ReturnType<typeof taskReducer>
export const taskReducer = (state, action: Actions) => {
switch (action.type) {
case "TASK_FETCH":
return { isFetching: true }
case "TASK_SUCCESS":
return { isFetching: false, task: action.payload }
case "TASK_FAIL":
return { isFetching: false, error: action.payload }
}
const _exhaustiveCheck: never = action
return state
}
State
рд╢рд╛рдк рджреЗрдирд╛ рдмрдВрдж рдХрд░ рджрд┐рдпрд╛, рд▓реЗрдХрд┐рди рдЕрдм рд╡рд╣ рд╣реИ any
, рдХреНрдпреЛрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдЪрдХреНрд░реАрдп рдирд┐рд░реНрднрд░рддрд╛ рд╣реИред рд╣рдо рддрд░реНрдХ рдЯрд╛рдЗрдк рдХрд░рддреЗ рд╣реИрдВредtype State = ReturnType<typeof taskReducer>
export const taskReducer = (state: { isFetching: true }, action: Actions) => {
switch (action.type) {
case "TASK_FETCH":
return { isFetching: true }
case "TASK_SUCCESS":
return { isFetching: false, task: action.payload }
case "TASK_FAIL":
return { isFetching: false, error: action.payload }
}
const _exhaustiveCheck: never = action
return state
}
рдирд┐рд╖реНрдХрд░реНрд╖ рддреИрдпрд╛рд░ рд╣реИред
рдирд┐рд╖реНрдХрд░реНрд╖ рд╣реИ рдХрд┐ рд╣рдо рдХреНрдпрд╛ рдореВрд▓ рд░реВрдк рд╕реЗ рдХрд┐рдпрд╛ рдерд╛ рдХреЗ рд╕рдорд╛рди рд╣реИ: true
, false
, Task
ред рдпрд╣рд╛рдВ рдХрдЪрд░рд╛ рдХреНрд╖реЗрддреНрд░ рд╣реИрдВ Error
, рд▓реЗрдХрд┐рди рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде undefined
- рдХреНрд╖реЗрддреНрд░ рд╡рд╣рд╛рдВ рд▓рдЧрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдРрд╕рд╛ рдирд╣реАрдВ рд▓рдЧрддрд╛ рд╣реИредрдЪреМрдерд╛ рдЯрд┐рдк
рдУрд╡рд░рд╡рд░реНрдХ рди рдХрд░реЗрдВред
рдпрджрд┐ рдЖрдк рдЖрд░рд╛рдо рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдмрд╣реБрдд рдЧрд╣рд░рд╛рдИ рд╕реЗ рдЧреЛрддрд╛ рд▓рдЧрд╛рддреЗ рд╣реИрдВ, рддреЛ рд╡рд╛рдкрд╕ рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рдСрдХреНрд╕реАрдЬрди рдирд╣реАрдВ рд╣реЛ рд╕рдХрддреА рд╣реИредрдкреНрд░рд╢рд┐рдХреНрд╖рдг рднреА: рдпрджрд┐ рдЖрдк рднреА рдкреНрд░реМрджреНрдпреЛрдЧрд┐рдХреА рдореЗрдВ рдбреВрдмреЗ рд╣реБрдП рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рд╣рд░ рдЬрдЧрд╣ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓реЗрддреЗ рд╣реИрдВ, рддреЛ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛ рд╣реИ рдХрд┐ рдЖрдк рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░реЗрдВрдЧреЗ, рдЬрд┐рдирдХреЗ рдХрд╛рд░рдг рдЖрдк рдирд╣реАрдВ рдЬрд╛рдирддреЗ рд╣реИрдВред рдпрд╣ рдЕрд╕реНрд╡реАрдХреГрддрд┐ рдХрд╛ рдХрд╛рд░рдг рдмрдиреЗрдЧрд╛ рдФрд░ рдЕрдм рд╕реНрдереИрддрд┐рдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣реЗрдЧрд╛ред рдЕрдкрдиреА рддрд╛рдХрдд рдХрд╛ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВредрдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рд╡рд┐рдХрд╛рд╕ рдХреЛ рдХреИрд╕реЗ рдзреАрдорд╛ рдХрд░рддрд╛ рд╣реИ
рдЯрд╛рдЗрдкрд┐рдВрдЧ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдореЗрдВ рдХреБрдЫ рд╕рдордп рд▓рдЧреЗрдЧрд╛ред рдЗрд╕рдореЗрдВ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдпреВрдПрдХреНрд╕ рдирд╣реАрдВ рд╣реИ - рдХрднреА-рдХрднреА рдпрд╣ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрдпреЛрдЧреНрдп рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рджреЗрддрд╛ рд╣реИ, рдХрд┐рд╕реА рдЕрдиреНрдп рдкреНрд░рдХрд╛рд░ рдХреА рдкреНрд░рдгрд╛рд▓реА рдХреА рддрд░рд╣, рдЬреИрд╕реЗ рдлреНрд▓реЛ рдпрд╛ рдорд╛рд╕реНрдХреЗрд▓редрд╕рд┐рд╕реНрдЯрдо рдЬрд┐рддрдирд╛ рдЕрдзрд┐рдХ рд╕реНрдкрд╖реНрдЯ рд╣реЛрдЧрд╛, рддреНрд░реБрдЯрд┐ рдЙрддрдиреА рд╣реА рдХрдард┐рди рд╣реЛрдЧреАред
рдкреНрд░рдХрд╛рд░ рдкреНрд░рдгрд╛рд▓реА рдХрд╛ рдореВрд▓реНрдп рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реЛрдиреЗ рдкрд░ рддреНрд╡рд░рд┐рдд рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рд╕рд┐рд╕реНрдЯрдо рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░реЗрдЧрд╛ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдЦреЛрдЬрдиреЗ рдФрд░ рдареАрдХ рдХрд░рдиреЗ рдореЗрдВ рдХрдо рд╕рдордп рд▓рдЧреЗрдЧрд╛ред рдпрджрд┐ рдЖрдк рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдареАрдХ рдХрд░рдиреЗ рдореЗрдВ рдХрдо рд╕рдордп рд▓рдЧрд╛рддреЗ рд╣реИрдВ, рддреЛ рдЕрдзрд┐рдХ рд╡рд╛рд╕реНрддреБ рд╕рдорд╛рдзрд╛рдиреЛрдВ рдкрд░ рдЕрдзрд┐рдХ рдзреНрдпрд╛рди рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдпрджрд┐ рдЖрдк рдЙрдирдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рд╕реАрдЦрддреЗ рд╣реИрдВ рддреЛ рдкреНрд░рдХрд╛рд░ рд╡рд┐рдХрд╛рд╕ рдХреЛ рдзреАрдорд╛ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред++. - , , (25 26 ) - (27 тАФ 10 ).
(5900 ), ++ IT-, .
AvitoTech FrontendConf 2019 . youtube- telegram @FrontendConfChannel, .