import { getTransferFee, transferMoneyNow } from 'awesome-apis';
const TransferInput = ({onComplete, onError}) => {
const [transferFee, setTransferFee] = useState(null);
const [transferAmount, setTransferAmount] = useState(null);
React.userEffect(() => {
getTransferFee().then(res => setTransferFee(res.transferFee));
}, [])
const handleTransfer = () => {
if(transferAmount && transferFee)
transferMoneyNow({ amountWithFee: transferAmount + transferFee }).then(onComplete);
else
onError();
}
return (
<TransferView>
<Input value={transferAmount} onChange={setTransferAmount} />
<Button text="Transfer" onPress={handleTransfer} />
</TransferView>
);
}import { getTransferFee, transferMoneyNow } from 'awesome-apis';
const TransferInput = ({onComplete, onError}) => {
const [transferFee, setTransferFee] = useState(null);
const [transferAmount, setTransferAmount] = useState(null);
React.userEffect(() => {
getTransferFee().then(res => setTransferFee(res.transferFee));
}, [])
const handleTransfer = () => {
if(transferAmount && transferFee)
transferMoneyNow({ amountWithFee: transferAmount + transferFee }).then(onComplete);
else
onError(); // Error 💥
}
return (
<TransferView>
<Input value={transferAmount} onChange={setTransferAmount} />
<Button text="Transfer" onPress={handleTransfer} />
</TransferView>
);
}import { getTransferFee, transferMoneyNow } from 'awesome-apis';
const TransferInput = ({onComplete, onError}) => {
const [transferFee, setTransferFee] = useState(null);
const [transferAmount, setTransferAmount] = useState(null);
React.userEffect(() => {
getTransferFee().then(res => setTransferFee(res.transferFee));
}, [])
const handleTransfer = () => {
if(transferAmount && transferFee)
transferMoneyNow({ amountWithFee: transferAmount + transferFee }).then(onComplete);
else
onError(); // Error 💥
}
return (
<TransferView>
<Input value={transferAmount} onChange={setTransferAmount} />
<Button text="Transfer" onPress={handleTransfer} />
</TransferView>
);
}import { getTransferFee, transferMoneyNow } from 'awesome-apis';
const TransferInput = ({onComplete, onError}) => {
const [transferFee, setTransferFee] = useState(null);
const [transferAmount, setTransferAmount] = useState(null);
React.userEffect(() => {
getTransferFee().then(res => console.log(res.transferFee)); // Log: undefined
}, [])
const handleTransfer = () => {
console.log(transferAmount, transferFee); // Log: 399, undefined
if(transferAmount && transferFee)
transferMoneyNow({ amountWithFee: transferAmount + transferFee }).then(onComplete);
else
onError(); // Error 💥
}
return (
<TransferView>
<Input value={transferAmount} onChange={setTransferAmount} />
<Button text="Transfer" onPress={handleTransfer} />
</TransferView>
);
}import { getTransferFee, transferMoneyNow } from 'awesome-apis';
const TransferInput = ({onComplete, onError}) => {
const [transferFee, setTransferFee] = useState(null);
const [transferAmount, setTransferAmount] = useState(null);
React.userEffect(() => {
getTransferFee().then(res => console.log(res.transferFee)); // Log: undefined
}, [])
const handleTransfer = () => {
console.log(transferAmount, transferFee); // Log: 399, undefined
if(transferAmount && transferFee)
transferMoneyNow({ amountWithFee: transferAmount + transferFee }).then(onComplete);
else
onError(); // Error 💥
}
return (
<TransferView>
<Input value={transferAmount} onChange={setTransferAmount} />
<Button text="Transfer" onPress={handleTransfer} />
</TransferView>
);
}So its time to talk with backend guys
import { getTransferFee, transferMoneyNow } from 'awesome-apis';
const TransferInput = ({onComplete, onError}) => {
const [transferFee, setTransferFee] = useState(null);
const [transferAmount, setTransferAmount] = useState(null);
React.userEffect(() => {
getTransferFee().then(res => console.log(res)); // Log: { Currency: "DKK", TransferFee: 4.00 } ✅
}, [])
const handleTransfer = () => {
console.log(transferAmount, transferFee); // Log: 399, undefined
if(transferAmount && transferFee)
transferMoneyNow({ amountWithFee: transferAmount + transferFee }).then(onComplete);
else
onError(); // Error 💥
}
return (
<TransferView>
<Input value={transferAmount} onChange={setTransferAmount} />
<Button text="Transfer" onPress={handleTransfer} />
</TransferView>
);
}import { getTransferFee, transferMoneyNow } from 'awesome-apis';
const TransferInput = ({onComplete, onError}) => {
const [transferFee, setTransferFee] = useState(null);
const [transferAmount, setTransferAmount] = useState(null);
React.userEffect(() => {
getTransferFee().then(res => setTransferFee(res.TrasferFee));
}, [])
const handleTransfer = () => {
if(transferAmount && transferFee)
transferMoneyNow({ amountWithFee: transferAmount + transferFee }).then(onComplete);
else
onError();
}
return (
<TransferView>
<Input value={transferAmount} onChange={setTransferAmount} />
<Button text="Transfer" onPress={handleTransfer} />
</TransferView>
);
}import { getTransferFee, transferMoneyNow } from 'awesome-apis';
const TransferInput = ({onComplete, onError}) => {
const [transferFee, setTransferFee] = useState(null);
const [transferAmount, setTransferAmount] = useState(null);
React.userEffect(() => {
getTransferFee().then(res => setTransferFee(res.TrasferFee));
}, [])
const handleTransfer = () => {
if(transferAmount && transferFee)
transferMoneyNow({ amountWithFee: transferAmount + transferFee }).then(onComplete);
else
onError();
}
return (
<TransferView>
<Input value={transferAmount} onChange={setTransferAmount} />
<Button text="Transfer" onPress={handleTransfer} />
</TransferView>
);
}import { getTransferFee, transferMoneyNow } from 'awesome-apis';
const TransferInput = ({onComplete, onError}) => {
const [transferFee, setTransferFee] = useState(null);
const [transferAmount, setTransferAmount] = useState(null);
React.userEffect(() => {
getTransferFee().then(res => setTransferFee(res.TrasferFee));
}, [])
const handleTransfer = () => {
if(transferAmount && transferFee)
transferMoneyNow({ amountWithFee: transferAmount + transferFee }).then(onComplete); // 💥 { amountWithFee: "3994.00" }
else
onError();
}
return (
<TransferView>
<Input value={transferAmount} onChange={setTransferAmount} />
<Button text="Transfer" onPress={handleTransfer} />
</TransferView>
);
}import { getTransferFee, transferMoneyNow } from 'awesome-apis';
const TransferInput = ({onComplete, onError}) => {
const [transferFee, setTransferFee] = useState(null);
const [transferAmount, setTransferAmount] = useState(null);
React.userEffect(() => {
getTransferFee().then(res => setTransferFee(res.TrasferFee));
}, [])
const handleTransfer = () => {
if(transferAmount && transferFee)
transferMoneyNow({ amountWithFee: transferAmount + transferFee }).then(onComplete); // ✅ { amountWithFee: "403.00" }
else
onError();
}
const handleChange = (value) => setTransferAmount(parseFloat(value));
return (
<TransferView>
<Input value={transferAmount} onChange={handleChange} />
<Button text="Transfer" onPress={handleTransfer} />
</TransferView>
);
}import { getTransferFee, transferMoneyNow } from 'awesome-apis';
const TransferInput = ({onComplete, onError}) => {
const [transferFee, setTransferFee] = useState(null);
const [transferAmount, setTransferAmount] = useState(null);
React.userEffect(() => {
getTransferFee().then(res => setTransferFee(res.TrasferFee));
}, [])
const handleTransfer = () => {
if(transferAmount && transferFee)
transferMoneyNow({ amountWithFee: transferAmount + transferFee }).then(onComplete); // ✅ { amountWithFee: "403.00" }
else
onError();
}
return (
<TransferView>
<Input value={transferAmount} onChange={setTransferAmount} type="number" />
<Button text="Transfer" onPress={handleTransfer} />
</TransferView>
);
}import { getTransferFee, transferMoneyNow } from 'awesome-apis';
const TransferInput = ({onComplete, onError}) => {
const [transferFee, setTransferFee] = useState(null);
const [transferAmount, setTransferAmount] = useState(null);
React.userEffect(() => {
getTransferFee().then(res => setTransferFee(res.TrasferFee));
}, [])
const handleTransfer = () => {
if(transferAmount && transferFee)
transferMoneyNow({ amountWithFee: transferAmount + transferFee }).then(onComplete); // ✅ { amountWithFee: 403.00 }
else
onError();
}
const handleChange = (value) => setTransferAmount(parseFloat(value));
return (
<TransferView>
<Input value={transferAmount} onChange={handleChange} />
<Button text="Transfer" onPress={handleTransfer} />
</TransferView>
);
}What
Why
How
import { getTransferFee, transferMoneyNow } from 'awesome-apis';
interface ITransferInputProps {
onComplete: () => void;
onError: () => void;
}
const TransferInput: React.FunctionComponent<ITransferInputProps> = ({onComplete, onError}) => {
const [transferFee, setTransferFee] = useState<number>(null);
const [transferAmount, setTransferAmount] = useState<number>(null);
React.userEffect(() => {
getTransferFee().then(res => setTransferFee(res.transferFee));
}, [])
const handleTransfer = () => {
if(transferAmount && transferFee)
transferMoneyNow({ amountWithFee: transferAmount + transferFee }).then(onComplete);
else
onError();
}
return (
<TransferView>
<Input value={transferAmount} onChange={setTransferAmount} />
<Button text="Transfer" onPress={handleTransfer} />
</TransferView>
);
}import { getTransferFee, transferMoneyNow } from 'awesome-apis';
interface ITransferInputProps {
onComplete: () => void;
onError: () => void;
}
const TransferInput: React.FunctionComponent<ITransferInputProps> = ({onComplete, onError}) => {
const [transferFee, setTransferFee] = useState<number>(null);
const [transferAmount, setTransferAmount] = useState<number>(null);
React.userEffect(() => {
getTransferFee().then(res => setTransferFee(res.transferFee)); // Property 'transferFee' does not exist on type IGetTransferFeeResponse. Did you mean 'TransferFee'?
}, [])
const handleTransfer = () => {
if(transferAmount && transferFee)
transferMoneyNow({ amountWithFee: transferAmount + transferFee }).then(onComplete); // Type error: string is not assignable to number
else
onError();
}
return (
<TransferView>
<Input value={transferAmount} onChange={setTransferAmount} /> // Type error: string is not assignable to number
<Button text="Transfer" onPress={handleTransfer} />
</TransferView>
);
}import { getTransferFee, transferMoneyNow } from 'awesome-apis';
interface ITransferInputProps {
onComplete: () => void;
onError: () => void;
}
const TransferInput: React.FunctionComponent<ITransferInputProps> = ({onComplete, onError}) => {
const [transferFee, setTransferFee] = useState<number>(null);
const [transferAmount, setTransferAmount] = useState<number>(null);
React.userEffect(() => {
getTransferFee().then(res => setTransferFee(res.TransferFee));
}, [])
const handleTransfer = () => {
if(transferAmount && transferFee)
transferMoneyNow({ amountWithFee: transferAmount + transferFee }).then(onComplete);
else
onError();
}
return (
<TransferView>
<Input value={transferAmount} onChange={setTransferAmount} type="number" />
<Button text="Transfer" onPress={handleTransfer} />
</TransferView>
);
}How did type="number" fix the type error?
interface IInputProps {
value: string;
onChange: (value: string) => void;
}
const Input: React.FunctionComponent<IInputProps> = (props) => {
return (
<FabricInput style="denim" value={props.value} onChange={props.onChange}/>
);
}
interface IInputProps {
type: "text" | "number";
value: string |Â number;
onChange: (value: string |Â number) => void;
}
const Input: React.FunctionComponent<IInputProps> = (props) => {
return (
<FabricInput style="denim" value={props.value} onChange={props.onChange}/>
);
}
type AllowedTypes = "text" | "number";
type TypeToValueType<Type extends AllowedTypes> =
Type extends "text"
? string
: Type extends "number"
? number
: string | number;
interface IInputProps<Type extends AllowedTypes = "text"> {
type?: Type;
value: TypeToValueType<Type>;
onChange: (value: TypeToValueType<Type>) => void;
}
const Input = <Type extends AllowedTypes>(props: IInputProps<Type>) => {
return (
<FabricInput style="denim" value={props.value} onChange={props.onChange}/>
);
}
type AllowedTypes = "text" | "number";
type TypeToValueType<Type extends AllowedTypes> =
Type extends "text"
? string
: Type extends "number"
? number
: string | number;
interface IInputProps<Type extends AllowedTypes = "text"> {
type?: Type;
value: TypeToValueType<Type>;
onChange: (value: TypeToValueType<Type>) => void;
}
const Input = <Type extends AllowedTypes>(props: IInputProps<Type>) => {
return (
<FabricInput style="denim" value={props.value} onChange={props.onChange}/> // 💥
);
}
type AllowedTypes = "text" | "number";
type TypeToValueType<Type extends AllowedTypes> =
Type extends "text"
? string
: Type extends "number"
? number
: string | number;
interface IInputProps<Type extends AllowedTypes = "text"> {
type?: Type;
value: TypeToValueType<Type>;
onChange: (value: TypeToValueType<Type>) => void;
}
const Input = <Type extends AllowedTypes>(props: IInputProps<Type>) => {
return (
<FabricInput style="denim" value={props.value} onChange={props.onChange}/> // 💥
);
}
type AllowedTypes = "text" | "number";
type TypeToValueType<Type extends AllowedTypes> =
Type extends "text"
? string
: Type extends "number"
? number
: string | number;
interface IInputProps<Type extends AllowedTypes = "text"> {
type?: Type;
value: TypeToValueType<Type>;
onChange: (value: TypeToValueType<Type>) => void;
}
const Input = <Type extends AllowedTypes>(props: IInputProps<Type>) => {
const getValue = (value: string | number) => {
return props.type === "number" ? props.value.toString() : props.value;
}
const handleChange = (value: string) => {
props.onChange(props.type === "number" ? parseFloat(value) : props.value);
}
return (
<FabricInput style="denim" value={getValue(props.value)} onChange={handleChange}/>
);
}
// Infer types
const pickItem = <List extends any[], Index extends number>(list: List, index: Index): List[Index] => {
return list[index];
}
const a = pickItem(["a", 1], 1); // a: string | number;// Infer types
const pickItem = <List extends any[], Index extends number>(list: List, index: Index): List[Index] => {
return list[index];
}
const a = pickItem(["a", 1], 1); // a: string | number;
const pickItem = <List extends ReadonlyArray<any>, Index extends number>(list: List, index: Index): List[Index] => {
return list[index];
}
const a = pickItem(["a", 1] as const, 1); // a: number;// Nullish Coalescing & Optional Chaining
interface IUser {
email: 'john@doe.com'
username: 'JohnDoe88',
info?: {
firstName: string;
lastName: string;
balance?: number
}
}
interface IBalanceInfoProps {
user?: IUser;
}
const BalanceInfo = (props: IBalanceInfoProps) => {
const balance = user && user.info && user.info.balance;
return (
<Text>{balance ? balance : "Not available"}</Text>
);
};// Nullish Coalescing & Optional Chaining
interface IUser {
email: 'john@doe.com'
username: 'JohnDoe88',
info?: {
firstName: string;
lastName: string;
balance?: number
}
}
interface IBalanceInfoProps {
user?: IUser;
}
const BalanceInfo = (props: IBalanceInfoProps) => {
const balance = user && user.info && user.info.balance;
return (
<Text>{balance ? balance : "Not available"}</Text>
);
};
// 💥 Shows "Not available" instead of 0...// Nullish Coalescing & Optional Chaining
interface IUser {
email: 'john@doe.com'
username: 'JohnDoe88',
info?: {
firstName: string;
lastName: string;
balance?: number
}
}
interface IBalanceInfoProps {
user?: IUser;
}
const BalanceInfo = (props: IBalanceInfoProps) => {
const balance = user?.info?.balance;
return (
<Text>{balance ?? "Not available"}</Text>
);
};
// ✅ Shows 0 instead of "Not available"// Discriminated Unions
type Shape = {
kind: "square" | "rectangle" | "circle";
size?: number;
width?: number;
height?: number;
radius?: number;
}
interface IAwesomeShapeProps<S extends Shape> {
shape: S;
}
const AwesomeShape = <S extends Shape>(props: IAwesomeShapeProps<S>) => {
if (props.shape.kind === "square")
return <Square size={props.shape.size || 0} />;
if (props.shape.kind === "rectangle")
return <Rectangle width={props.shape.size || 0} height={props.shape.size || 0} />;
if (props.shape.kind === "circle")
return <Circle radius={props.shape.radius || 0} />;
};// Discriminated Unions
type Shape = {
kind: "square" | "rectangle" | "circle";
size?: number;
width?: number;
height?: number;
radius?: number;
}
interface IAwesomeShapeProps<S extends Shape> {
shape: S;
}
const AwesomeShape = <S extends Shape>(props: IAwesomeShapeProps<S>) => {
if (props.shape.kind === "square")
return <Square size={props.shape.size || 0} />;
if (props.shape.kind === "rectangle")
return <Rectangle width={props.shape.size || 0} height={props.shape.size || 0} />;
if (props.shape.kind === "circle")
return <Circle radius={props.shape.radius || 0} />;
return <Text>{`Missing props for kind ${props.shape.kind}`}</Text>;
};// Discriminated Unions
interface ISquare {
kind: "square";
size: number;
}
interface IRectangle {
kind: "rectangle";
width: number;
height: number;
}
interface ICircle {
kind: "circle";
radius: number;
}
type Shape = Square | Rectangle | Circle;
interface IAwesomeShapeProps<S extends Shape> {
shape: S;
}
const AwesomeShape = <S extends Shape>(props: IAwesomeShapeProps<S>) => {
if (props.shape.kind === "square")
return <Square size={props.shape.size} />;
if (props.shape.kind === "rectangle")
return <Rectangle width={props.shape.size} height={props.shape.size} />;
if (props.shape.kind === "circle")
return <Circle radius={props.shape.radius} />;
};Basic Types
Interfaces
Generics
Generics
Conditional Types
utility-types
utility
immer-reducer
state system
80% devs wants TS
state of JS
Use strict mode
tip
async, readonly...
new features
better error messages
TS 3.7
utility-types
utility
immer-reducer
state system
80% devs wants TS
state of JS
Use strict mode
tip
async, readonly...
new features
better error messages
TS 3.7