interface AppProps {
// define props and types
}
const App = (props: AppProps) => {
// use props and render UI
}
interface AppProps {
message: string
}
const App = (props: AppProps) => {
if (props.loading) {
return <span>Loading...</span>
}
return <div>{props.message}</div>
}
Property 'loading' does not exist on type 'AppProps'
<App message="hi" count={5} />
Property 'count' does not exist on type
'IntrinsicAttributes & AppProps'
interface AppProps {
names: string[]
count: number
}
<App
names={['Bron', 'Jokic', 'Embiid', 'Luka', 'Giannis']}
/>
Property 'count' is missing in type '{ names: string[]; }'
but required in type 'AppProps'
interface AppProps {
names: string[]
count?: number
}
const App = ({ names, count = 2 }: AppProps) => {
const topPlayers = names.slice(0, count)
// render topPlayers in UI
}
<App
id="2"
names={['Bron', 'Jokic', 'Embiid', 'Luka', 'Giannis']}
/>
Property 'names' does not exist on type
'IntrinsicAttributes & AppProps'.
interface Address { /* city, isPrimary, etc */ }
interface User {
name: string
addresses: {
shipping: Address
billing?: Address
}
}
interface AppProps {
user: User
}
<App
user={{
user: { id: '1234', name: 'Ben', addresses: { } }
}}
/>
Property 'id' does not exist on type
'IntrinsicAttributes & User'.
const Input = ({ name, value, onChange }) => {
// do input-y stuff & call onChange
}
Input.propTypes = {
variant: PropTypes.enum(['filled', 'outlined']).isRequired,
value: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
}
interface Props {
variant: 'filled' | 'outlined'
value: string
onChange: (newValue: string) => void
}
const Input = ({ name, value, onChange }: Props) => {
// do input-y stuff & call onChange
}
useState
const App = () => {
const [count, setCount] = useState(0)
const add = () => {
setCount(
(prevCount) => prevCount + 1
)
}
return <button onClick={add}>Add</button>
}
useState
const App = () => {
const [user, setUser] = useState<User | null>(null)
useEffect(() => {
getUserApi().then((data) => {
setUser(data.user)
})
}, [])
}
return user ? <User user={user} /> : null
useEffect
const App = () => {
const [user, setUser] = useState<User | null>(null)
useEffect(() => (
getUserApi().then((data) => {
setUser(data.user)
})
), [])
}
Type 'Promise<void>' provides no match for the
signature '(): void | undefined'.
const useUser = (initUsername?: string) => {
const [username, setUsername] = useState(initUsername)
const [user, setUser] = useState<User | null>(null)
useEffect(() => {
getUser(username).then(setUser)
}, [username])
return [user, setUsername] as const
// want tuple: [User, (username: string) => void]
// not array: (User | (username: string) => void)[]
}
Valid configurations
<Text>not truncated<Text>
<Text truncate>truncated<Text>
<Text truncate showExpand>truncated w/ expand<Text>
Invalid configurations
<Text truncate={false} showExpand>not truncated<Text>
<Text showExpand>only expand<Text>
Property 'truncate' is missing in type
'{ children: Element; showExpanded: true; }' but required in type
'{ truncate: true; showExpanded?: boolean | undefined; }'.
interface CommonProps {
children: React.ReactNode,
// other props...
}
type TruncateProps =
| { truncate?: false, showExpanded: undefined }
| { truncate: true, showExpanded?: boolean }
type TextProps = CommonProps & TruncateProps
const Text = (props: TextProps) => {
// props.truncate = boolean | undefined
// props.showExpanded = boolean | undefined
}
<Button
variant="primary"
size="large"
type="button"
onClick={() => { /* ... */ }}
disabled
id="main_btn"
>
Go
</Button>
interface ExtraProps {
variant: 'primary' | 'secondary'
size: 'default' | 'small' | 'large'
}
type Props = ExtraProps
& Omit<React.ComponentProps<"button">, keyof ExtraProps>
const Button = ({ variant, size, ...buttonProps }: Props) => {
// do stuff with variant & size
return <button {...buttonProps} />
}
Waller Goble
10:00a (Room ABE)
tsconfig.json
@typescript-eslint/eslint-plugin