Property does not exist on type error with Union Types in Typescript Reac + Redux
I am new to React and Redux and I am making a small project using Typescript. I created my first reducer and actions, but I have a problem: whenever I try to access the payload's contents I get a Type error: property X does not exist in type
.
Actions:
import { Action } from 'redux';
export const LOGIN_ACTION = 'login';
export const LOGIN_SUCCESS_ACTION = 'login-sucesss';
export const LOGIN_FAILED_ACTION = 'login-failed';
export interface LoginAction extends Action {
type: string;
payload: {
username: string;
password: string;
};
}
export function login(username: string, password: string): LoginAction {
return {
type: LOGIN_ACTION,
payload: { username, password },
};
}
export interface LoginSuccessAction extends Action {
type: string;
payload: {
loginToken: string;
};
}
export function loginSuccess(loginToken: string): LoginSuccessAction {
return {
type: LOGIN_SUCCESS_ACTION,
payload: { loginToken },
};
}
export interface LoginFailedAction extends Action {
type: string;
payload: {
error: Error;
};
}
export function loginFailed(error: Error): LoginFailedAction {
return {
type: LOGIN_FAILED_ACTION,
payload: { error },
};
}
export type LoginActions = LoginAction | LoginSuccessAction | LoginFailedAction;
Reducer:
import { LOGIN_ACTION, LOGIN_FAILED_ACTION, LOGIN_SUCCESS_ACTION, LoginActions } from '../../actions/login.action';
import {
REQ_STATUS_FAIL,
REQ_STATUS_PROCESSING,
REQ_STATUS_SUCCESS,
REQ_STATUS_UNDEFINED,
} from '../../common/request-status';
export interface LoginState {
username: string;
password: string;
loginToken: string;
loginError?: Error;
status?: number;
}
export const initialState: LoginState = {
username: '',
password: '',
loginToken: '',
loginError: undefined,
status: REQ_STATUS_UNDEFINED,
};
export function loginReducer(state: LoginState = initialState, action: LoginActions): LoginState {
switch (action.type) {
case LOGIN_ACTION:
console.log('I was here', action.payload);
return { ...state, username: action.payload.username, password: action.payload.password, status: REQ_STATUS_PROCESSING };
case LOGIN_SUCCESS_ACTION:
return { ...state, loginToken: action.payload.loginToken, status: REQ_STATUS_SUCCESS };
case LOGIN_FAILED_ACTION:
return { ...state, loginToken: '', loginError: action.payload.error, status: REQ_STATUS_FAIL };
default:
return state;
}
}
The problem is that I have a lot of type errors when accessing the payload's properties, such as here: action.payload.username
or action.payload.password
.
Property 'username' does not exist on type '{ username: string; password: string; } | { loginToken: string; } | { error: Error; }'.
Property 'username' does not exist on type '{ loginToken: string; }'
Property 'password' does not exist on type '{ username: string; password: string; } | { loginToken: string; } | { error: Error; }'.
Property 'password' does not exist on type '{ loginToken: string; }'.
Could you help me?
reactjs typescript redux react-redux
add a comment |
I am new to React and Redux and I am making a small project using Typescript. I created my first reducer and actions, but I have a problem: whenever I try to access the payload's contents I get a Type error: property X does not exist in type
.
Actions:
import { Action } from 'redux';
export const LOGIN_ACTION = 'login';
export const LOGIN_SUCCESS_ACTION = 'login-sucesss';
export const LOGIN_FAILED_ACTION = 'login-failed';
export interface LoginAction extends Action {
type: string;
payload: {
username: string;
password: string;
};
}
export function login(username: string, password: string): LoginAction {
return {
type: LOGIN_ACTION,
payload: { username, password },
};
}
export interface LoginSuccessAction extends Action {
type: string;
payload: {
loginToken: string;
};
}
export function loginSuccess(loginToken: string): LoginSuccessAction {
return {
type: LOGIN_SUCCESS_ACTION,
payload: { loginToken },
};
}
export interface LoginFailedAction extends Action {
type: string;
payload: {
error: Error;
};
}
export function loginFailed(error: Error): LoginFailedAction {
return {
type: LOGIN_FAILED_ACTION,
payload: { error },
};
}
export type LoginActions = LoginAction | LoginSuccessAction | LoginFailedAction;
Reducer:
import { LOGIN_ACTION, LOGIN_FAILED_ACTION, LOGIN_SUCCESS_ACTION, LoginActions } from '../../actions/login.action';
import {
REQ_STATUS_FAIL,
REQ_STATUS_PROCESSING,
REQ_STATUS_SUCCESS,
REQ_STATUS_UNDEFINED,
} from '../../common/request-status';
export interface LoginState {
username: string;
password: string;
loginToken: string;
loginError?: Error;
status?: number;
}
export const initialState: LoginState = {
username: '',
password: '',
loginToken: '',
loginError: undefined,
status: REQ_STATUS_UNDEFINED,
};
export function loginReducer(state: LoginState = initialState, action: LoginActions): LoginState {
switch (action.type) {
case LOGIN_ACTION:
console.log('I was here', action.payload);
return { ...state, username: action.payload.username, password: action.payload.password, status: REQ_STATUS_PROCESSING };
case LOGIN_SUCCESS_ACTION:
return { ...state, loginToken: action.payload.loginToken, status: REQ_STATUS_SUCCESS };
case LOGIN_FAILED_ACTION:
return { ...state, loginToken: '', loginError: action.payload.error, status: REQ_STATUS_FAIL };
default:
return state;
}
}
The problem is that I have a lot of type errors when accessing the payload's properties, such as here: action.payload.username
or action.payload.password
.
Property 'username' does not exist on type '{ username: string; password: string; } | { loginToken: string; } | { error: Error; }'.
Property 'username' does not exist on type '{ loginToken: string; }'
Property 'password' does not exist on type '{ username: string; password: string; } | { loginToken: string; } | { error: Error; }'.
Property 'password' does not exist on type '{ loginToken: string; }'.
Could you help me?
reactjs typescript redux react-redux
add a comment |
I am new to React and Redux and I am making a small project using Typescript. I created my first reducer and actions, but I have a problem: whenever I try to access the payload's contents I get a Type error: property X does not exist in type
.
Actions:
import { Action } from 'redux';
export const LOGIN_ACTION = 'login';
export const LOGIN_SUCCESS_ACTION = 'login-sucesss';
export const LOGIN_FAILED_ACTION = 'login-failed';
export interface LoginAction extends Action {
type: string;
payload: {
username: string;
password: string;
};
}
export function login(username: string, password: string): LoginAction {
return {
type: LOGIN_ACTION,
payload: { username, password },
};
}
export interface LoginSuccessAction extends Action {
type: string;
payload: {
loginToken: string;
};
}
export function loginSuccess(loginToken: string): LoginSuccessAction {
return {
type: LOGIN_SUCCESS_ACTION,
payload: { loginToken },
};
}
export interface LoginFailedAction extends Action {
type: string;
payload: {
error: Error;
};
}
export function loginFailed(error: Error): LoginFailedAction {
return {
type: LOGIN_FAILED_ACTION,
payload: { error },
};
}
export type LoginActions = LoginAction | LoginSuccessAction | LoginFailedAction;
Reducer:
import { LOGIN_ACTION, LOGIN_FAILED_ACTION, LOGIN_SUCCESS_ACTION, LoginActions } from '../../actions/login.action';
import {
REQ_STATUS_FAIL,
REQ_STATUS_PROCESSING,
REQ_STATUS_SUCCESS,
REQ_STATUS_UNDEFINED,
} from '../../common/request-status';
export interface LoginState {
username: string;
password: string;
loginToken: string;
loginError?: Error;
status?: number;
}
export const initialState: LoginState = {
username: '',
password: '',
loginToken: '',
loginError: undefined,
status: REQ_STATUS_UNDEFINED,
};
export function loginReducer(state: LoginState = initialState, action: LoginActions): LoginState {
switch (action.type) {
case LOGIN_ACTION:
console.log('I was here', action.payload);
return { ...state, username: action.payload.username, password: action.payload.password, status: REQ_STATUS_PROCESSING };
case LOGIN_SUCCESS_ACTION:
return { ...state, loginToken: action.payload.loginToken, status: REQ_STATUS_SUCCESS };
case LOGIN_FAILED_ACTION:
return { ...state, loginToken: '', loginError: action.payload.error, status: REQ_STATUS_FAIL };
default:
return state;
}
}
The problem is that I have a lot of type errors when accessing the payload's properties, such as here: action.payload.username
or action.payload.password
.
Property 'username' does not exist on type '{ username: string; password: string; } | { loginToken: string; } | { error: Error; }'.
Property 'username' does not exist on type '{ loginToken: string; }'
Property 'password' does not exist on type '{ username: string; password: string; } | { loginToken: string; } | { error: Error; }'.
Property 'password' does not exist on type '{ loginToken: string; }'.
Could you help me?
reactjs typescript redux react-redux
I am new to React and Redux and I am making a small project using Typescript. I created my first reducer and actions, but I have a problem: whenever I try to access the payload's contents I get a Type error: property X does not exist in type
.
Actions:
import { Action } from 'redux';
export const LOGIN_ACTION = 'login';
export const LOGIN_SUCCESS_ACTION = 'login-sucesss';
export const LOGIN_FAILED_ACTION = 'login-failed';
export interface LoginAction extends Action {
type: string;
payload: {
username: string;
password: string;
};
}
export function login(username: string, password: string): LoginAction {
return {
type: LOGIN_ACTION,
payload: { username, password },
};
}
export interface LoginSuccessAction extends Action {
type: string;
payload: {
loginToken: string;
};
}
export function loginSuccess(loginToken: string): LoginSuccessAction {
return {
type: LOGIN_SUCCESS_ACTION,
payload: { loginToken },
};
}
export interface LoginFailedAction extends Action {
type: string;
payload: {
error: Error;
};
}
export function loginFailed(error: Error): LoginFailedAction {
return {
type: LOGIN_FAILED_ACTION,
payload: { error },
};
}
export type LoginActions = LoginAction | LoginSuccessAction | LoginFailedAction;
Reducer:
import { LOGIN_ACTION, LOGIN_FAILED_ACTION, LOGIN_SUCCESS_ACTION, LoginActions } from '../../actions/login.action';
import {
REQ_STATUS_FAIL,
REQ_STATUS_PROCESSING,
REQ_STATUS_SUCCESS,
REQ_STATUS_UNDEFINED,
} from '../../common/request-status';
export interface LoginState {
username: string;
password: string;
loginToken: string;
loginError?: Error;
status?: number;
}
export const initialState: LoginState = {
username: '',
password: '',
loginToken: '',
loginError: undefined,
status: REQ_STATUS_UNDEFINED,
};
export function loginReducer(state: LoginState = initialState, action: LoginActions): LoginState {
switch (action.type) {
case LOGIN_ACTION:
console.log('I was here', action.payload);
return { ...state, username: action.payload.username, password: action.payload.password, status: REQ_STATUS_PROCESSING };
case LOGIN_SUCCESS_ACTION:
return { ...state, loginToken: action.payload.loginToken, status: REQ_STATUS_SUCCESS };
case LOGIN_FAILED_ACTION:
return { ...state, loginToken: '', loginError: action.payload.error, status: REQ_STATUS_FAIL };
default:
return state;
}
}
The problem is that I have a lot of type errors when accessing the payload's properties, such as here: action.payload.username
or action.payload.password
.
Property 'username' does not exist on type '{ username: string; password: string; } | { loginToken: string; } | { error: Error; }'.
Property 'username' does not exist on type '{ loginToken: string; }'
Property 'password' does not exist on type '{ username: string; password: string; } | { loginToken: string; } | { error: Error; }'.
Property 'password' does not exist on type '{ loginToken: string; }'.
Could you help me?
reactjs typescript redux react-redux
reactjs typescript redux react-redux
asked Nov 20 '18 at 14:37
FelipeFelipe
1,22411731
1,22411731
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
You are trying to use discriminated unions in typescript. Discriminated unions work with switch
statements in order to narrow the type on each branch according to a given property (type
in your case). A requirement of discriminated unions is for the type
property to be a literal type (in your case a string literal type). Since you define constants for the type of the action you can use typeof constant
to get the string literal type inferred for the constant.
interface Action { } // Dummy for self contained sample
export const LOGIN_ACTION = 'login';
export const LOGIN_SUCCESS_ACTION = 'login-sucesss';
export const LOGIN_FAILED_ACTION = 'login-failed';
export interface LoginAction extends Action {
type: typeof LOGIN_ACTION; // !! here we assign the string literal type of the constant
payload: {
username: string;
password: string;
};
}
export function login(username: string, password: string): LoginAction {
return {
type: LOGIN_ACTION,
payload: { username, password },
};
}
export interface LoginSuccessAction extends Action {
type: typeof LOGIN_SUCCESS_ACTION; // !! here we assign the string literal type of the constant
payload: {
loginToken: string;
};
}
export function loginSuccess(loginToken: string): LoginSuccessAction {
return {
type: LOGIN_SUCCESS_ACTION,
payload: { loginToken },
};
}
export interface LoginFailedAction extends Action {
type: typeof LOGIN_FAILED_ACTION; // !! here we assign the string literal type of the constant
payload: {
error: Error;
};
}
export function loginFailed(error: Error): LoginFailedAction {
return {
type: LOGIN_FAILED_ACTION,
payload: { error },
};
}
export type LoginActions = LoginAction | LoginSuccessAction | LoginFailedAction;
export interface LoginState {
username: string;
password: string;
loginToken: string;
loginError?: Error;
status?: number;
}
export const initialState: LoginState = {
username: '',
password: '',
loginToken: '',
loginError: undefined,
status: 0,
};
export function loginReducer(state: LoginState = initialState, action: LoginActions): LoginState {
// Type guard fro discriminated union.
switch (action.type) {
case LOGIN_ACTION:
console.log('I was here', action.payload);
// action is LoginAction here
return { ...state, username: action.payload.username, password: action.payload.password, status: 0};
case LOGIN_SUCCESS_ACTION:
// action is LoginSuccessAction here
return { ...state, loginToken: action.payload.loginToken, status: 1 };
case LOGIN_FAILED_ACTION:
// action is LoginFailedAction here
return { ...state, loginToken: '', loginError: action.payload.error, status: -1 };
default:
return state;
}
}
Thanks for the answer. I suppose that I could also use an Enum, right?
– Felipe
Nov 20 '18 at 15:40
Yes but similar rules apply, you would have to use a value of enum as a type to get the switch to narrow the type
– Titian Cernicova-Dragomir
Nov 20 '18 at 15:43
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53395372%2fproperty-does-not-exist-on-type-error-with-union-types-in-typescript-reac-redu%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You are trying to use discriminated unions in typescript. Discriminated unions work with switch
statements in order to narrow the type on each branch according to a given property (type
in your case). A requirement of discriminated unions is for the type
property to be a literal type (in your case a string literal type). Since you define constants for the type of the action you can use typeof constant
to get the string literal type inferred for the constant.
interface Action { } // Dummy for self contained sample
export const LOGIN_ACTION = 'login';
export const LOGIN_SUCCESS_ACTION = 'login-sucesss';
export const LOGIN_FAILED_ACTION = 'login-failed';
export interface LoginAction extends Action {
type: typeof LOGIN_ACTION; // !! here we assign the string literal type of the constant
payload: {
username: string;
password: string;
};
}
export function login(username: string, password: string): LoginAction {
return {
type: LOGIN_ACTION,
payload: { username, password },
};
}
export interface LoginSuccessAction extends Action {
type: typeof LOGIN_SUCCESS_ACTION; // !! here we assign the string literal type of the constant
payload: {
loginToken: string;
};
}
export function loginSuccess(loginToken: string): LoginSuccessAction {
return {
type: LOGIN_SUCCESS_ACTION,
payload: { loginToken },
};
}
export interface LoginFailedAction extends Action {
type: typeof LOGIN_FAILED_ACTION; // !! here we assign the string literal type of the constant
payload: {
error: Error;
};
}
export function loginFailed(error: Error): LoginFailedAction {
return {
type: LOGIN_FAILED_ACTION,
payload: { error },
};
}
export type LoginActions = LoginAction | LoginSuccessAction | LoginFailedAction;
export interface LoginState {
username: string;
password: string;
loginToken: string;
loginError?: Error;
status?: number;
}
export const initialState: LoginState = {
username: '',
password: '',
loginToken: '',
loginError: undefined,
status: 0,
};
export function loginReducer(state: LoginState = initialState, action: LoginActions): LoginState {
// Type guard fro discriminated union.
switch (action.type) {
case LOGIN_ACTION:
console.log('I was here', action.payload);
// action is LoginAction here
return { ...state, username: action.payload.username, password: action.payload.password, status: 0};
case LOGIN_SUCCESS_ACTION:
// action is LoginSuccessAction here
return { ...state, loginToken: action.payload.loginToken, status: 1 };
case LOGIN_FAILED_ACTION:
// action is LoginFailedAction here
return { ...state, loginToken: '', loginError: action.payload.error, status: -1 };
default:
return state;
}
}
Thanks for the answer. I suppose that I could also use an Enum, right?
– Felipe
Nov 20 '18 at 15:40
Yes but similar rules apply, you would have to use a value of enum as a type to get the switch to narrow the type
– Titian Cernicova-Dragomir
Nov 20 '18 at 15:43
add a comment |
You are trying to use discriminated unions in typescript. Discriminated unions work with switch
statements in order to narrow the type on each branch according to a given property (type
in your case). A requirement of discriminated unions is for the type
property to be a literal type (in your case a string literal type). Since you define constants for the type of the action you can use typeof constant
to get the string literal type inferred for the constant.
interface Action { } // Dummy for self contained sample
export const LOGIN_ACTION = 'login';
export const LOGIN_SUCCESS_ACTION = 'login-sucesss';
export const LOGIN_FAILED_ACTION = 'login-failed';
export interface LoginAction extends Action {
type: typeof LOGIN_ACTION; // !! here we assign the string literal type of the constant
payload: {
username: string;
password: string;
};
}
export function login(username: string, password: string): LoginAction {
return {
type: LOGIN_ACTION,
payload: { username, password },
};
}
export interface LoginSuccessAction extends Action {
type: typeof LOGIN_SUCCESS_ACTION; // !! here we assign the string literal type of the constant
payload: {
loginToken: string;
};
}
export function loginSuccess(loginToken: string): LoginSuccessAction {
return {
type: LOGIN_SUCCESS_ACTION,
payload: { loginToken },
};
}
export interface LoginFailedAction extends Action {
type: typeof LOGIN_FAILED_ACTION; // !! here we assign the string literal type of the constant
payload: {
error: Error;
};
}
export function loginFailed(error: Error): LoginFailedAction {
return {
type: LOGIN_FAILED_ACTION,
payload: { error },
};
}
export type LoginActions = LoginAction | LoginSuccessAction | LoginFailedAction;
export interface LoginState {
username: string;
password: string;
loginToken: string;
loginError?: Error;
status?: number;
}
export const initialState: LoginState = {
username: '',
password: '',
loginToken: '',
loginError: undefined,
status: 0,
};
export function loginReducer(state: LoginState = initialState, action: LoginActions): LoginState {
// Type guard fro discriminated union.
switch (action.type) {
case LOGIN_ACTION:
console.log('I was here', action.payload);
// action is LoginAction here
return { ...state, username: action.payload.username, password: action.payload.password, status: 0};
case LOGIN_SUCCESS_ACTION:
// action is LoginSuccessAction here
return { ...state, loginToken: action.payload.loginToken, status: 1 };
case LOGIN_FAILED_ACTION:
// action is LoginFailedAction here
return { ...state, loginToken: '', loginError: action.payload.error, status: -1 };
default:
return state;
}
}
Thanks for the answer. I suppose that I could also use an Enum, right?
– Felipe
Nov 20 '18 at 15:40
Yes but similar rules apply, you would have to use a value of enum as a type to get the switch to narrow the type
– Titian Cernicova-Dragomir
Nov 20 '18 at 15:43
add a comment |
You are trying to use discriminated unions in typescript. Discriminated unions work with switch
statements in order to narrow the type on each branch according to a given property (type
in your case). A requirement of discriminated unions is for the type
property to be a literal type (in your case a string literal type). Since you define constants for the type of the action you can use typeof constant
to get the string literal type inferred for the constant.
interface Action { } // Dummy for self contained sample
export const LOGIN_ACTION = 'login';
export const LOGIN_SUCCESS_ACTION = 'login-sucesss';
export const LOGIN_FAILED_ACTION = 'login-failed';
export interface LoginAction extends Action {
type: typeof LOGIN_ACTION; // !! here we assign the string literal type of the constant
payload: {
username: string;
password: string;
};
}
export function login(username: string, password: string): LoginAction {
return {
type: LOGIN_ACTION,
payload: { username, password },
};
}
export interface LoginSuccessAction extends Action {
type: typeof LOGIN_SUCCESS_ACTION; // !! here we assign the string literal type of the constant
payload: {
loginToken: string;
};
}
export function loginSuccess(loginToken: string): LoginSuccessAction {
return {
type: LOGIN_SUCCESS_ACTION,
payload: { loginToken },
};
}
export interface LoginFailedAction extends Action {
type: typeof LOGIN_FAILED_ACTION; // !! here we assign the string literal type of the constant
payload: {
error: Error;
};
}
export function loginFailed(error: Error): LoginFailedAction {
return {
type: LOGIN_FAILED_ACTION,
payload: { error },
};
}
export type LoginActions = LoginAction | LoginSuccessAction | LoginFailedAction;
export interface LoginState {
username: string;
password: string;
loginToken: string;
loginError?: Error;
status?: number;
}
export const initialState: LoginState = {
username: '',
password: '',
loginToken: '',
loginError: undefined,
status: 0,
};
export function loginReducer(state: LoginState = initialState, action: LoginActions): LoginState {
// Type guard fro discriminated union.
switch (action.type) {
case LOGIN_ACTION:
console.log('I was here', action.payload);
// action is LoginAction here
return { ...state, username: action.payload.username, password: action.payload.password, status: 0};
case LOGIN_SUCCESS_ACTION:
// action is LoginSuccessAction here
return { ...state, loginToken: action.payload.loginToken, status: 1 };
case LOGIN_FAILED_ACTION:
// action is LoginFailedAction here
return { ...state, loginToken: '', loginError: action.payload.error, status: -1 };
default:
return state;
}
}
You are trying to use discriminated unions in typescript. Discriminated unions work with switch
statements in order to narrow the type on each branch according to a given property (type
in your case). A requirement of discriminated unions is for the type
property to be a literal type (in your case a string literal type). Since you define constants for the type of the action you can use typeof constant
to get the string literal type inferred for the constant.
interface Action { } // Dummy for self contained sample
export const LOGIN_ACTION = 'login';
export const LOGIN_SUCCESS_ACTION = 'login-sucesss';
export const LOGIN_FAILED_ACTION = 'login-failed';
export interface LoginAction extends Action {
type: typeof LOGIN_ACTION; // !! here we assign the string literal type of the constant
payload: {
username: string;
password: string;
};
}
export function login(username: string, password: string): LoginAction {
return {
type: LOGIN_ACTION,
payload: { username, password },
};
}
export interface LoginSuccessAction extends Action {
type: typeof LOGIN_SUCCESS_ACTION; // !! here we assign the string literal type of the constant
payload: {
loginToken: string;
};
}
export function loginSuccess(loginToken: string): LoginSuccessAction {
return {
type: LOGIN_SUCCESS_ACTION,
payload: { loginToken },
};
}
export interface LoginFailedAction extends Action {
type: typeof LOGIN_FAILED_ACTION; // !! here we assign the string literal type of the constant
payload: {
error: Error;
};
}
export function loginFailed(error: Error): LoginFailedAction {
return {
type: LOGIN_FAILED_ACTION,
payload: { error },
};
}
export type LoginActions = LoginAction | LoginSuccessAction | LoginFailedAction;
export interface LoginState {
username: string;
password: string;
loginToken: string;
loginError?: Error;
status?: number;
}
export const initialState: LoginState = {
username: '',
password: '',
loginToken: '',
loginError: undefined,
status: 0,
};
export function loginReducer(state: LoginState = initialState, action: LoginActions): LoginState {
// Type guard fro discriminated union.
switch (action.type) {
case LOGIN_ACTION:
console.log('I was here', action.payload);
// action is LoginAction here
return { ...state, username: action.payload.username, password: action.payload.password, status: 0};
case LOGIN_SUCCESS_ACTION:
// action is LoginSuccessAction here
return { ...state, loginToken: action.payload.loginToken, status: 1 };
case LOGIN_FAILED_ACTION:
// action is LoginFailedAction here
return { ...state, loginToken: '', loginError: action.payload.error, status: -1 };
default:
return state;
}
}
answered Nov 20 '18 at 14:45
Titian Cernicova-DragomirTitian Cernicova-Dragomir
66.1k34361
66.1k34361
Thanks for the answer. I suppose that I could also use an Enum, right?
– Felipe
Nov 20 '18 at 15:40
Yes but similar rules apply, you would have to use a value of enum as a type to get the switch to narrow the type
– Titian Cernicova-Dragomir
Nov 20 '18 at 15:43
add a comment |
Thanks for the answer. I suppose that I could also use an Enum, right?
– Felipe
Nov 20 '18 at 15:40
Yes but similar rules apply, you would have to use a value of enum as a type to get the switch to narrow the type
– Titian Cernicova-Dragomir
Nov 20 '18 at 15:43
Thanks for the answer. I suppose that I could also use an Enum, right?
– Felipe
Nov 20 '18 at 15:40
Thanks for the answer. I suppose that I could also use an Enum, right?
– Felipe
Nov 20 '18 at 15:40
Yes but similar rules apply, you would have to use a value of enum as a type to get the switch to narrow the type
– Titian Cernicova-Dragomir
Nov 20 '18 at 15:43
Yes but similar rules apply, you would have to use a value of enum as a type to get the switch to narrow the type
– Titian Cernicova-Dragomir
Nov 20 '18 at 15:43
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53395372%2fproperty-does-not-exist-on-type-error-with-union-types-in-typescript-reac-redu%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown