# Buggy code
def init_dict(data: Dict, index, columns, dtype: Optional[DtypeObj] = None):
    """
    Segregate Series based on type and coerce into matrices.
    Needs to handle a lot of exceptional cases.
    """
    arrays: Union[Sequence[Any], "Series"]

    if columns is not None:
        from pandas.core.series import Series  # noqa:F811

        arrays = Series(data, index=columns, dtype=object)
        data_names = arrays.index

        missing = arrays.isna()
        if index is None:
            # GH10856
            # raise ValueError if only scalars in dict
            index = extract_index(arrays[~missing])
        else:
            index = ensure_index(index)

        # no obvious "empty" int column
        if missing.any() and not is_integer_dtype(dtype):
            if dtype is None or np.issubdtype(dtype, np.flexible):
                # GH#1783
                nan_dtype = np.dtype(object)
            else:
                nan_dtype = dtype
            val = construct_1d_arraylike_from_scalar(np.nan, len(index), nan_dtype)
            arrays.loc[missing] = [val] * missing.sum()

    else:
        keys = list(data.keys())
        columns = data_names = Index(keys)
        arrays = [com.maybe_iterable_to_list(data[k]) for k in keys]
        # GH#24096 need copy to be deep for datetime64tz case
        # TODO: See if we can avoid these copies
        arrays = [
            arr if not isinstance(arr, ABCIndexClass) else arr._data for arr in arrays
        ]
        arrays = [
            arr if not is_datetime64tz_dtype(arr) else arr.copy() for arr in arrays
        ]
    return arrays_to_mgr(arrays, data_names, index, columns, dtype=dtype)


# Traceback (TypeError)
In [1]: import pandas as pd

In [2]: pd.DataFrame({'a': ['b']}, dtype='string')
Out[2]:
a
0  b

In [3]: pd.DataFrame(columns=['a'], dtype='string')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-2e577cc30885> in <module>
----> 1 pd.DataFrame(columns=['a'], dtype='string')

~/lib/miniconda/envs/xport/lib/python3.8/site-packages/pandas/core/frame.py in __init__(self, data, index, columns, dtype, copy)
433             )
434         elif isinstance(data, dict):
--> 435             mgr = init_dict(data, index, columns, dtype=dtype)
436         elif isinstance(data, ma.MaskedArray):
437             import numpy.ma.mrecords as mrecords

~/lib/miniconda/envs/xport/lib/python3.8/site-packages/pandas/core/internals/construction.py in init_dict(data, index, columns, dtype)
232         # no obvious "empty" int column
233         if missing.any() and not is_integer_dtype(dtype):
--> 234             if dtype is None or np.issubdtype(dtype, np.flexible):
235                 # GH#1783
236                 nan_dtype = object

~/lib/miniconda/envs/xport/lib/python3.8/site-packages/numpy/core/numerictypes.py in issubdtype(arg1, arg2)
391     """
392     if not issubclass_(arg1, generic):
--> 393         arg1 = dtype(arg1).type
394     if not issubclass_(arg2, generic):
395         arg2_orig = arg2

TypeError: data type not understood

In [4]: pd.DataFrame(columns=['a'], dtype='float')
Out[4]:
Empty DataFrame
Columns: [a]
Index: []

# Fixed code
def init_dict(data: Dict, index, columns, dtype: Optional[DtypeObj] = None):
    """
    Segregate Series based on type and coerce into matrices.
    Needs to handle a lot of exceptional cases.
    """
    arrays: Union[Sequence[Any], "Series"]

    if columns is not None:
        from pandas.core.series import Series  # noqa:F811

        arrays = Series(data, index=columns, dtype=object)
        data_names = arrays.index

        missing = arrays.isna()
        if index is None:
            # GH10856
            # raise ValueError if only scalars in dict
            index = extract_index(arrays[~missing])
        else:
            index = ensure_index(index)

        # no obvious "empty" int column
        if missing.any() and not is_integer_dtype(dtype):
            if dtype is None or (
                not is_extension_array_dtype(dtype)
                and np.issubdtype(dtype, np.flexible)
            ):
                # GH#1783
                nan_dtype = np.dtype(object)
            else:
                nan_dtype = dtype
            val = construct_1d_arraylike_from_scalar(np.nan, len(index), nan_dtype)
            arrays.loc[missing] = [val] * missing.sum()

    else:
        keys = list(data.keys())
        columns = data_names = Index(keys)
        arrays = [com.maybe_iterable_to_list(data[k]) for k in keys]
        # GH#24096 need copy to be deep for datetime64tz case
        # TODO: See if we can avoid these copies
        arrays = [
            arr if not isinstance(arr, ABCIndexClass) else arr._data for arr in arrays
        ]
        arrays = [
            arr if not is_datetime64tz_dtype(arr) else arr.copy() for arr in arrays
        ]
    return arrays_to_mgr(arrays, data_names, index, columns, dtype=dtype)