mirror of
https://github.com/denoland/deno.git
synced 2025-01-15 18:38:53 -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,
|
npm_resolver,
|
||||||
)
|
)
|
||||||
.with_context(|| {
|
.with_context(|| {
|
||||||
format!("Error resolving package config for '{}'.", reference)
|
format!("Error resolving package config for '{}'", reference)
|
||||||
})?;
|
})?;
|
||||||
let resolved_path = match maybe_resolved_path {
|
let resolved_path = match maybe_resolved_path {
|
||||||
Some(resolved_path) => resolved_path,
|
Some(resolved_path) => resolved_path,
|
||||||
|
|
|
@ -279,7 +279,7 @@ mod npm {
|
||||||
exit_code: 1,
|
exit_code: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
itest!(types {
|
itest!(types_general {
|
||||||
args: "check --quiet npm/types/main.ts",
|
args: "check --quiet npm/types/main.ts",
|
||||||
output: "npm/types/main.out",
|
output: "npm/types/main.out",
|
||||||
envs: env_vars_for_npm_tests(),
|
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'.
|
error: TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
||||||
bar: 1,
|
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'
|
The expected type comes from property 'bar' which is declared here on type 'Foobar'
|
||||||
bar: string;
|
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'.
|
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
||||||
prop: 1,
|
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'
|
The expected type comes from property 'prop' which is declared here on type 'SomeInterface'
|
||||||
prop: string;
|
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'.
|
TS2322 [ERROR]: Type 'string' is not assignable to type 'number'.
|
||||||
prop2: "asdf",
|
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'
|
The expected type comes from property 'prop2' which is declared here on type 'SomeInterface'
|
||||||
prop2: number;
|
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'.
|
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
||||||
fizz: 1,
|
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'
|
The expected type comes from property 'fizz' which is declared here on type 'Fizzbuzz'
|
||||||
fizz: string;
|
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'.
|
TS2322 [ERROR]: Type 'number' is not assignable to type 'string'.
|
||||||
buzz: 2,
|
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'
|
The expected type comes from property 'buzz' which is declared here on type 'Fizzbuzz'
|
||||||
buzz: string;
|
buzz: string;
|
||||||
~~~~
|
~~~~
|
||||||
at [WILDCARD]/@denotest/types/1.0.0/index.d.ts:3:3
|
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 { Fizzbuzz } from "npm:@denotest/types";
|
||||||
import type { SomeInterface } from "npm:@denotest/types_imported";
|
import type { SomeInterface } from "npm:@denotest/types_imported";
|
||||||
import type { Foobar as FooInterface } from "npm:@denotest/types_imported/subpath";
|
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 = {
|
const foobar: FooInterface = {
|
||||||
foo: "foo",
|
foo: "foo",
|
||||||
|
@ -16,3 +19,7 @@ const fizzbuzz: Fizzbuzz = {
|
||||||
fizz: 1,
|
fizz: 1,
|
||||||
buzz: 2,
|
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.
|
// 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::generic_error;
|
||||||
use deno_core::error::type_error;
|
use deno_core::error::type_error;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
@ -61,13 +63,26 @@ pub fn err_invalid_package_target(
|
||||||
) -> AnyError {
|
) -> AnyError {
|
||||||
let rel_error = !is_import && !target.is_empty() && !target.starts_with("./");
|
let rel_error = !is_import && !target.is_empty() && !target.starts_with("./");
|
||||||
let mut msg = "[ERR_INVALID_PACKAGE_TARGET]".to_string();
|
let mut msg = "[ERR_INVALID_PACKAGE_TARGET]".to_string();
|
||||||
|
let pkg_json_path = PathBuf::from(pkg_path).join("package.json");
|
||||||
|
|
||||||
if key == "." {
|
if key == "." {
|
||||||
assert!(!is_import);
|
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 {
|
} else {
|
||||||
let ie = if is_import { "imports" } else { "exports" };
|
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 {
|
if let Some(base) = maybe_referrer {
|
||||||
|
|
|
@ -502,14 +502,6 @@ fn resolve_package_target(
|
||||||
{
|
{
|
||||||
let condition_target = target_obj.get(key).unwrap().to_owned();
|
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(
|
let resolved = resolve_package_target(
|
||||||
package_json_path,
|
package_json_path,
|
||||||
condition_target,
|
condition_target,
|
||||||
|
|
Loading…
Reference in a new issue