public static function coerceType($value, string $type)
    {
        if ($value === null) {
            return null;
        }

        if (self::isTypedArrayType($type) && self::isValidArrayOfType($value, $type)) {
            $arrayType = self::getTypeOfTypedArrayType($type);
            return array_map(function ($value) use ($arrayType) {
                return self::coerceType($value, $arrayType);
            }, $value);
        }

        switch ($type) {
            case "mixed":
                return $value;
            case "double":
            case "float":
                if (is_numeric($value)) {
                    return (float)$value;
                }
                break;
            case "int":
                if (is_numeric($value)) {
                    return (int)$value;
                }
                break;
            case "string":
                return is_bool($value) ? self::booleanStringValue($value) : (string)$value;
            case 'bool':
                return self::toBooleanValue($value);
            default:
                if (gettype($value) === $type || gettype($value) === "object" && get_class($value) === $type) {
                    return $value;
                }
                break;
        }
        throw new TypeCoercionException("Could not coerce to type '$type'.");
    }