diff --git a/src/Base/Transformer/TsAssocArrayTransformer.php b/src/Base/Transformer/TsAssocArrayTransformer.php index b3097a8..d34d40a 100644 --- a/src/Base/Transformer/TsAssocArrayTransformer.php +++ b/src/Base/Transformer/TsAssocArrayTransformer.php @@ -22,9 +22,7 @@ public static function canTransform(Type $type, Scope $scope, ReflectionProvider return false; } - $keyType = $type->getKeyType(); - - return ! $keyType instanceof \PHPStan\Type\IntegerType; + return $type->getKeyType()->isInteger()->no(); } public static function transform(Type $type, Scope $scope, ReflectionProvider $reflectionProvider): TsType { diff --git a/src/Base/Transformer/TsSimpleArrayTransformer.php b/src/Base/Transformer/TsSimpleArrayTransformer.php index 27d94c1..d0baf5d 100644 --- a/src/Base/Transformer/TsSimpleArrayTransformer.php +++ b/src/Base/Transformer/TsSimpleArrayTransformer.php @@ -9,6 +9,7 @@ use PHPStan\Analyser\Scope; use PHPStan\Reflection\ReflectionProvider; use PHPStan\Type\ArrayType; +use PHPStan\Type\StringType; /** * A simple homogeneous array type. For example: `string[]`, `number[]`, `(string | number)[]`, `never[]`, etc. @@ -20,9 +21,7 @@ public static function canTransform(Type $type, Scope $scope, ReflectionProvider return false; } - $keyType = $type->getKeyType(); - - return $keyType instanceof \PHPStan\Type\IntegerType; + return !$type->getKeyType()->isInteger()->no(); } public static function transform(Type $type, Scope $scope, ReflectionProvider $reflectionProvider): TsSimpleArrayType { diff --git a/src/Base/Transformer/_ArrayLikeParserHelper.php b/src/Base/Transformer/_ArrayLikeParserHelper.php index 0ea2928..7d1e51c 100644 --- a/src/Base/Transformer/_ArrayLikeParserHelper.php +++ b/src/Base/Transformer/_ArrayLikeParserHelper.php @@ -13,7 +13,7 @@ class _ArrayLikeParserHelper { public static function transform(Type $keyType, Type $valueType, Scope $scope, ReflectionProvider $reflectionProvider): TsSimpleArrayType|TsRecordType { - if ($keyType->isInteger()->yes()) { + if (!$keyType->isInteger()->no()) { return new TsSimpleArrayType(TsTransformer::transform($valueType, $scope, $reflectionProvider)); } diff --git a/src/LaravelData/Transformer/LaravelDataPaginatedTransformer.php b/src/LaravelData/Transformer/LaravelDataPaginatedTransformer.php index 00b6f1a..cc00d96 100644 --- a/src/LaravelData/Transformer/LaravelDataPaginatedTransformer.php +++ b/src/LaravelData/Transformer/LaravelDataPaginatedTransformer.php @@ -21,12 +21,12 @@ public static function canTransform(Type $type, Scope $scope, ReflectionProvider $unionTypes = $type->getTypes(); - if (count($unionTypes) !== 2) { - return false; - } + // if (count($unionTypes) !== 2) { + // return false; + // } foreach ($unionTypes as $unionType) { - if (!$unionType instanceof \PHPStan\Type\ObjectType) { + if (!$unionType instanceof \PHPStan\Type\ObjectType && !$unionType instanceof \PHPStan\Type\ArrayType) { return false; } } @@ -40,10 +40,14 @@ public static function canTransform(Type $type, Scope $scope, ReflectionProvider } /** - * @param \PHPStan\Type\ObjectType[] $types + * @param (\PHPStan\Type\ObjectType | \PHPStan\Type\ArrayType)[] $types */ protected static function getPaginator(array $types, ReflectionProvider $reflectionProvider): ?Type { $paginator = array_filter($types, function ($type) use ($reflectionProvider) { + if (!$type instanceof \PHPStan\Type\ObjectType) { + return false; + } + if ($type->getClassName() === 'Illuminate\Pagination\AbstractPaginator') { return true; } @@ -57,11 +61,7 @@ protected static function getPaginator(array $types, ReflectionProvider $reflect return $reflection->isSubclassOfClass($reflectionProvider->getClass('Illuminate\Pagination\AbstractPaginator')); }); - if (count($paginator) === 1) { - return array_pop($paginator); - } - - return null; + return array_pop($paginator); } /** @@ -74,11 +74,7 @@ protected static function getPaginatedType(array $types): ?Type { return $type->isIterable()->yes(); }); - if (count($types) !== 1) { - return null; - } - - return array_pop($types)->getIterableValueType(); + return array_pop($types)?->getIterableValueType(); } public static function transform(Type $type, Scope $scope, ReflectionProvider $reflectionProvider): TsType { diff --git a/src/LaravelData/Transformer/LaravelDataTransformer.php b/src/LaravelData/Transformer/LaravelDataTransformer.php index 6fe378a..54d650c 100644 --- a/src/LaravelData/Transformer/LaravelDataTransformer.php +++ b/src/LaravelData/Transformer/LaravelDataTransformer.php @@ -12,6 +12,7 @@ use djfhe\PHPStanTypescriptTransformer\TsType; use djfhe\PHPStanTypescriptTransformer\Base\Types\TsObjectPropertyType; use djfhe\PHPStanTypescriptTransformer\Base\Types\TsObjectType; +use djfhe\PHPStanTypescriptTransformer\Base\Types\TsLiteralType; use djfhe\PHPStanTypescriptTransformer\TsTransformer; use PHPStan\Analyser\OutOfClassScope; use ReflectionProperty; @@ -147,7 +148,25 @@ protected static function parseLiteralTypescriptAttribute(array $attributes, Sco assert($arg !== null); - return TsTransformer::transform($arg, $scope, $reflectionProvider); + // $arg is a string or constant string type. if it we would transform it via ::transform, + // we would get a string with the content as its type. E.g.: + // #[LiteralTypeScriptType('{ a: string }')] + // public mixed $foo + // would be transformed to: + // foo: '{ a: string }' + // which is wrong. We need to directly handle the string content here. + + if (!$arg->isString()->yes()) { + return null; + } + + if ($arg instanceof \PHPStan\Type\Constant\ConstantStringType) { + $arg = $arg->getValue(); + } else { + $arg = 'unknown'; + } + + return new TsLiteralType($arg); } public static function transformPriority(Type $type, Scope $scope, ReflectionProvider $reflectionProvider, array $candidates): int