TypeScript & React Native: Using Pick to avoid bloating my code

I have the following interface and React Native component that uses it:

import { KeyboardTypeOptions, TextInputProps } from 'react-native';
import { TextInput } from 'react-native-paper';

export interface ValidatedInputProps {
    autoCapitalize?: 'none' | 'sentences' | 'words' | 'characters',
    contentType: Pick<TextInputProps, 'textContentType'>,
    isSecure?: boolean,
    keyboard?: KeyboardTypeOptions,
    label: string,
}

export const ValidatedInput = ({
    autoCapitalize = 'none',
    contentType,
    isSecure = false,
    keyboard = 'default',
    label,
}: ValidatedInputProps) => {
    return (
        <TextInput
            textContentType={contentType} <-- Error is flagged here
            ...other props
        />
    );
};

This gives me the following error popup in VSCode:

Type 'Pick<TextInputIOSProps, "textContentType">' is not assignable to type '"none" | "name" | "URL" | "addressCity" | "addressCityAndState" | "addressState" | "countryName" | "creditCardNumber" | "emailAddress" | "familyName" | "fullStreetAddress" | ... 17 more ... | undefined'.
  Type 'Pick<TextInputIOSProps, "textContentType">' is not assignable to type '"oneTimeCode"'.ts(2322)
index.d.ts(1250, 5): The expected type comes from property 'textContentType' which is declared here on type 'IntrinsicAttributes & Pick<TextInputProps, "textContentType" | "clearButtonMode" | "clearTextOnFocus" | "dataDetectorTypes" | "enablesReturnKeyAutomatically" | ... 114 more ... | "dense"> & { ...; } & { ...; }'
(JSX attribute) textContentType?: "none" | "name" | "URL" | "addressCity" | "addressCityAndState" | "addressState" | "countryName" | "creditCardNumber" | "emailAddress" | "familyName" | "fullStreetAddress" | ... 17 more ... | undefined

I’m obviously completely misunderstanding the point of the Pick<T, K> type, but everything that I’ve read on the subject over the past two hours seems to imply that my usage is correct. So what am I missing?

I guess I could define my contentType prop with the correct union (as I’ve done with autoCapitalize), but who would want to bloat their code with that excessively-long string of characters, when it’s already been defined elsewhere?! Can’t I just import that property/type and be done with it??

Answer

Pick<Type, Keys>

Constructs an Object type by picking the set of property Keys (string literal or union of string literals) from Type.

So it is not giving you the union of allowed values for textContentType, but an Object type with a single key of textContentType.

Instead you could extend a Picked version of TextInputProps with the properties you need, then add your own properties to the interface.

import { KeyboardTypeOptions, TextInputProps } from 'react-native';

export interface ValidatedInputProps extends Pick<TextInputProps, 'textContentType' | 'autoCapitalize'>  {
  isSecure?: boolean,
  keyboard?: KeyboardTypeOptions,
  label: string,
}

Alternatively you could just create local types by accessing each known property from the imported Object type.

import { KeyboardTypeOptions, TextInputProps } from 'react-native';

type myTextContentType = TextInputProps['textContentType']
type myAutoCapitalize = TextInputProps['autoCapitalize']

export interface ValidatedInputProps {
  textContentType?: myTextContentType,
  autoCapitalize?: myAutoCapitalize,
  isSecure?: boolean,
  keyboard?: KeyboardTypeOptions,
  label: string,
}