mirror of
https://github.com/denoland/deno.git
synced 2024-12-27 17:49:08 -05:00
fix(npm): improve exports resolution when type checking (#17071)
Closes #17012
This commit is contained in:
parent
f95b65d3c7
commit
98e7c91be4
12 changed files with 76 additions and 18 deletions
|
@ -522,7 +522,7 @@ pub fn node_resolve_npm_reference(
|
|||
npm_resolver,
|
||||
)
|
||||
.with_context(|| {
|
||||
format!("Error resolving package config for '{}'.", reference)
|
||||
format!("Error resolving package config for '{}'", reference)
|
||||
})?;
|
||||
let resolved_path = match maybe_resolved_path {
|
||||
Some(resolved_path) => resolved_path,
|
||||
|
|
|
@ -279,7 +279,7 @@ mod npm {
|
|||
exit_code: 1,
|
||||
});
|
||||
|
||||
itest!(types {
|
||||
itest!(types_general {
|
||||
args: "check --quiet npm/types/main.ts",
|
||||
output: "npm/types/main.out",
|
||||
envs: env_vars_for_npm_tests(),
|
||||
|
|
1
cli/tests/testdata/npm/registry/@denotest/types-exports-subpaths/1.0.0/client.d.ts
vendored
Normal file
1
cli/tests/testdata/npm/registry/@denotest/types-exports-subpaths/1.0.0/client.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
export function getClient(): 5;
|
3
cli/tests/testdata/npm/registry/@denotest/types-exports-subpaths/1.0.0/dist/client.mjs
vendored
Normal file
3
cli/tests/testdata/npm/registry/@denotest/types-exports-subpaths/1.0.0/dist/client.mjs
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
export function getClient() {
|
||||
return 5;
|
||||
}
|
1
cli/tests/testdata/npm/registry/@denotest/types-exports-subpaths/1.0.0/dist/entry-c.d.ts
vendored
Normal file
1
cli/tests/testdata/npm/registry/@denotest/types-exports-subpaths/1.0.0/dist/entry-c.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
export function entryC(): 12;
|
3
cli/tests/testdata/npm/registry/@denotest/types-exports-subpaths/1.0.0/dist/entry-c.js
vendored
Normal file
3
cli/tests/testdata/npm/registry/@denotest/types-exports-subpaths/1.0.0/dist/entry-c.js
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
export function entryC() {
|
||||
return 12;
|
||||
}
|
2
cli/tests/testdata/npm/registry/@denotest/types-exports-subpaths/1.0.0/entry-b.d.ts
vendored
Normal file
2
cli/tests/testdata/npm/registry/@denotest/types-exports-subpaths/1.0.0/entry-b.d.ts
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
// it will go to this and not the types entry because this entry was first
|
||||
export function entryB(): string;
|
19
cli/tests/testdata/npm/registry/@denotest/types-exports-subpaths/1.0.0/package.json
vendored
Normal file
19
cli/tests/testdata/npm/registry/@denotest/types-exports-subpaths/1.0.0/package.json
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "@denotest/types-exports-subpaths",
|
||||
"version": "1.0.0",
|
||||
"exports": {
|
||||
"./client": {
|
||||
"types": {
|
||||
"default": "./client.d.ts"
|
||||
},
|
||||
"import": "./dist/client.mjs"
|
||||
},
|
||||
"./entry-b": {
|
||||
"import": "./entry-b.d.ts",
|
||||
"types": "./dist/entry-b-wrong.d.ts"
|
||||
},
|
||||
"./entry-c": {
|
||||
"import": "./dist/entry-c.js"
|
||||
}
|
||||
}
|
||||
}
|
27
cli/tests/testdata/npm/types/main.out
vendored
27
cli/tests/testdata/npm/types/main.out
vendored
|
@ -1,7 +1,7 @@
|
|||
error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
||||
bar: 1,
|
||||
~~~
|
||||
at [WILDCARD]/npm/types/main.ts:7:3
|
||||
at [WILDCARD]/npm/types/main.ts:[WILDCARD]
|
||||
|
||||
The expected type comes from property 'bar' which is declared here on type 'Foobar'
|
||||
bar: string;
|
||||
|
@ -11,7 +11,7 @@ error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
|||
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
||||
prop: 1,
|
||||
~~~~
|
||||
at [WILDCARD]/npm/types/main.ts:11:3
|
||||
at [WILDCARD]/npm/types/main.ts:[WILDCARD]
|
||||
|
||||
The expected type comes from property 'prop' which is declared here on type 'SomeInterface'
|
||||
prop: string;
|
||||
|
@ -21,7 +21,7 @@ TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
|||
TS2322 [ERROR]: Type 'string' is not assignable to type 'number'.
|
||||
prop2: "asdf",
|
||||
~~~~~
|
||||
at [WILDCARD]/npm/types/main.ts:12:3
|
||||
at [WILDCARD]/npm/types/main.ts:[WILDCARD]
|
||||
|
||||
The expected type comes from property 'prop2' which is declared here on type 'SomeInterface'
|
||||
prop2: number;
|
||||
|
@ -31,7 +31,7 @@ TS2322 [ERROR]: Type 'string' is not assignable to type 'number'.
|
|||
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
||||
fizz: 1,
|
||||
~~~~
|
||||
at [WILDCARD]/npm/types/main.ts:16:3
|
||||
at [WILDCARD]/npm/types/main.ts:[WILDCARD]
|
||||
|
||||
The expected type comes from property 'fizz' which is declared here on type 'Fizzbuzz'
|
||||
fizz: string;
|
||||
|
@ -41,11 +41,26 @@ TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
|||
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
||||
buzz: 2,
|
||||
~~~~
|
||||
at [WILDCARD]/npm/types/main.ts:17:3
|
||||
at [WILDCARD]/npm/types/main.ts:[WILDCARD]
|
||||
|
||||
The expected type comes from property 'buzz' which is declared here on type 'Fizzbuzz'
|
||||
buzz: string;
|
||||
~~~~
|
||||
at [WILDCARD]/@denotest/types/1.0.0/index.d.ts:3:3
|
||||
|
||||
Found 5 errors.
|
||||
TS2322 [ERROR]: Type '5' is not assignable to type '"test1"'.
|
||||
const valueA: "test1" = getClient();
|
||||
~~~~~~
|
||||
at [WILDCARD]/npm/types/main.ts:[WILDCARD]
|
||||
|
||||
TS2322 [ERROR]: Type 'string' is not assignable to type '"test2"'.
|
||||
const valueB: "test2" = entryB();
|
||||
~~~~~~
|
||||
at [WILDCARD]/types/main.ts:[WILDCARD]
|
||||
|
||||
TS2322 [ERROR]: Type '12' is not assignable to type '"test3"'.
|
||||
const valueC: "test3" = entryC();
|
||||
~~~~~~
|
||||
at [WILDCARD]/types/main.ts:[WILDCARD]
|
||||
|
||||
Found 8 errors.
|
||||
|
|
7
cli/tests/testdata/npm/types/main.ts
vendored
7
cli/tests/testdata/npm/types/main.ts
vendored
|
@ -1,6 +1,9 @@
|
|||
import type { Fizzbuzz } from "npm:@denotest/types";
|
||||
import type { SomeInterface } from "npm:@denotest/types_imported";
|
||||
import type { Foobar as FooInterface } from "npm:@denotest/types_imported/subpath";
|
||||
import { getClient } from "npm:@denotest/types-exports-subpaths/client";
|
||||
import { entryB } from "npm:@denotest/types-exports-subpaths/entry-b";
|
||||
import { entryC } from "npm:@denotest/types-exports-subpaths/entry-c";
|
||||
|
||||
const foobar: FooInterface = {
|
||||
foo: "foo",
|
||||
|
@ -16,3 +19,7 @@ const fizzbuzz: Fizzbuzz = {
|
|||
fizz: 1,
|
||||
buzz: 2,
|
||||
};
|
||||
|
||||
const valueA: "test1" = getClient();
|
||||
const valueB: "test2" = entryB();
|
||||
const valueC: "test3" = entryC();
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use deno_core::error::generic_error;
|
||||
use deno_core::error::type_error;
|
||||
use deno_core::error::AnyError;
|
||||
|
@ -61,13 +63,26 @@ pub fn err_invalid_package_target(
|
|||
) -> AnyError {
|
||||
let rel_error = !is_import && !target.is_empty() && !target.starts_with("./");
|
||||
let mut msg = "[ERR_INVALID_PACKAGE_TARGET]".to_string();
|
||||
let pkg_json_path = PathBuf::from(pkg_path).join("package.json");
|
||||
|
||||
if key == "." {
|
||||
assert!(!is_import);
|
||||
msg = format!("{} Invalid \"exports\" main target {} defined in the package config {}package.json", msg, target, pkg_path)
|
||||
msg = format!(
|
||||
"{} Invalid \"exports\" main target {} defined in the package config {}",
|
||||
msg,
|
||||
target,
|
||||
pkg_json_path.display()
|
||||
)
|
||||
} else {
|
||||
let ie = if is_import { "imports" } else { "exports" };
|
||||
msg = format!("{} Invalid \"{}\" target {} defined for '{}' in the package config {}package.json", msg, ie, target, key, pkg_path)
|
||||
msg = format!(
|
||||
"{} Invalid \"{}\" target {} defined for '{}' in the package config {}",
|
||||
msg,
|
||||
ie,
|
||||
target,
|
||||
key,
|
||||
pkg_json_path.display()
|
||||
)
|
||||
};
|
||||
|
||||
if let Some(base) = maybe_referrer {
|
||||
|
|
|
@ -502,14 +502,6 @@ fn resolve_package_target(
|
|||
{
|
||||
let condition_target = target_obj.get(key).unwrap().to_owned();
|
||||
|
||||
if mode.is_types()
|
||||
&& key.as_str() != "types"
|
||||
&& condition_target.is_string()
|
||||
{
|
||||
// skip because this isn't a types entry
|
||||
continue;
|
||||
}
|
||||
|
||||
let resolved = resolve_package_target(
|
||||
package_json_path,
|
||||
condition_target,
|
||||
|
|
Loading…
Reference in a new issue