рдЙрдиреНрдирдд рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ

рдореБрдХреНрддрд┐ - рд╕реНрдХреВрдмрд╛ рдбрд╛рдЗрд╡рд┐рдВрдЧ рдХреЗ рдмрд┐рдирд╛ рд╕реНрдХреВрдмрд╛ рдбрд╛рдЗрд╡рд┐рдВрдЧред рдЧреЛрддрд╛рдЦреЛрд░ рдЖрд░реНрдХрд┐рдорд┐рдбреАрдЬ рдХреЗ рдХрд╛рдиреВрди рдХреЛ рдорд╣рд╕реВрд╕ рдХрд░рддрд╛ рд╣реИ: рд╡рд╣ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдорд╛рддреНрд░рд╛ рдореЗрдВ рдкрд╛рдиреА рдХреЛ рд╡рд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдЙрд╕реЗ рдкреАрдЫреЗ рдзрдХреЗрд▓рддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдкрд╣рд▓реЗ рдХреБрдЫ рдореАрдЯрд░реЛрдВ рдХреЛ рд╕рдмрд╕реЗ рдХрдард┐рди рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдлрд┐рд░ рдЖрдкрдХреЗ рдКрдкрд░ рдкрд╛рдиреА рдХреЗ рд╕реНрддрдВрдн рдХрд╛ рджрдмрд╛рд╡ рдмрд▓ рдЧрд╣рд░рд╛ рдЬрд╛рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рдиреЗ рд▓рдЧрддрд╛ рд╣реИред рдпрд╣ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкреНрд░рдХрд╛рд░ рдХреА рдкреНрд░рдгрд╛рд▓рд┐рдпреЛрдВ рдореЗрдВ рд╕реАрдЦрдиреЗ рдФрд░ рдбрд╛рдЗрд╡рд┐рдВрдЧ рдХреА рдпрд╛рдж рджрд┐рд▓рд╛рддреА рд╣реИ - рдЬреИрд╕реЗ рд╣реА рдЖрдк рдЧреЛрддрд╛ рд▓рдЧрд╛рддреЗ рд╣реИрдВ рдпрд╣ рдереЛрдбрд╝рд╛ рдЖрд╕рд╛рди рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╣рдореЗрдВ рд╕рдордп рдкрд░ рдЙрднрд░рдирд╛ рдирд╣реАрдВ рднреВрд▓рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╡рди рдУрд╢рди рд╡рди рдмреНрд░реЗрде


рд╕реЗ рдлреЛрдЯреЛ ред

рдорд┐рдЦрд╛рдЗрд▓ рдмрд╢реБрд░реЛрд╡ (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 }
        //case "TASK_FAIL":
            //return { isFetching: false, error: 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") {
        // log call
    }

    // prettier-ignore
    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, .

All Articles