镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

[bug] TemplateStringsArray is incompatible with literal array type #16552

Description

TypeScript Version: 2.4.0

Code

// A *self-contained* demonstration of the problem follows...
interface SQLQuery<TResult> {
  __result: TResult;
} 
declare function sql(
  literals: ['SELECT id FROM users'],
  ...placeholders: any[]
): SQLQuery<{id: number}>;

declare function querySync<TResult>(q: SQLQuery<TResult>): Array<TResult>;

const values: Array<{id: number}> = querySync(sql`SELECT id FROM users`);

Expected behavior:

Typescript should see that the input string 'SELECT id FROM users' matches the expected literals of ['SELECT id FROM users'] and use the declared function, allowing me to generate an overloaded version of the sql function for each query.

Actual behavior:

I get the error:

src/index.ts(23,50): error TS2345: Argument of type 'TemplateStringsArray' is not assignable to parameter of type '["SELECT id FROM users"]'.
Property '0' is missing in type 'TemplateStringsArray'.

Activity

  1. DanielRosenwasser commented on Jun 16, 2017

    @DanielRosenwasser
    Member

    I think this is contingent on #16592.

  2. DanielRosenwasser commented on Jun 16, 2017

    @DanielRosenwasser
    Member

    Actually, I don't know if this will work even with the changes I have in mind. TemplateStringsArray is effectively a ReadonlyArray<string> - but you can't assign a ReadonlyArray to a mutable Array. So at the minimum you'd have to write something like

    interface MyCustomType extends TemplateStringsArray {
      0: "SELECT id FROM users"
    }
  3. ForbesLindesay commented on Jun 19, 2017

    @ForbesLindesay
    ContributorAuthor

    That would be fine. I'm going to be auto-generating these definitions anyway, by parsing the code to see which functions are called. This would be very much a workaround for #16551.

    At the moment, that doesn't seem to work either though.

  4. pablobirukov commented on Jun 21, 2017

    @pablobirukov
    declare function id<T extends string>(list: Array<T>): Array<T>;
    declare function readonlyId<T extends string>(list: ReadonlyArray<T>): ReadonlyArray<T>;
    
    type LiteralType = "foo" | "bar";
    
    const array: Array<LiteralType> = [];
    const readonlyArray: ReadonlyArray<LiteralType> = [];
    
    const foo: ReadonlyArray<LiteralType> = id(array);
    const bar: ReadonlyArray<LiteralType> = readonlyId(array);
    //    ~~~
    // Type 'ReadonlyArray<string>' is not assignable to type 'ReadonlyArray<LiteralType>'.
    //  Type 'string' is not assignable to type 'LiteralType'.const bar: ReadonlyArray<LiteralType>
    const baz: ReadonlyArray<LiteralType> = readonlyId(readonlyArray);

    Isn't it a bug that generic type information is being lost when ReadonlyArray is assigned to Array?

  5. ForbesLindesay commented on Jun 23, 2017

    @ForbesLindesay
    ContributorAuthor

    Ronny Friman (@R00GER) that looks like a separate bug, it should probably have its own issue.

  6. RyanCavanaugh commented on Aug 15, 2018

    @RyanCavanaugh
    Member

    Daniel Rosenwasser (@DanielRosenwasser) can you give an update on next steps here?

  7. xialvjun commented on May 16, 2019

    @xialvjun

    There shouldn't be a type TemplateStringsArray, it should be a const string tuple type, so we can write code:

    interface SQL<TSA, VS> {
      texts: TSA;
      values: VS;
    }
    
    function sql<TSA extends readonly string[], VS extends any[]>(texts:TSA, ...values: VS): SQL<TSA, VS> {
      return { texts, values };
    }
    
    // then
    let s: SQL<['select * from person where a=', ' and b=', ''], [number, Date]> = sql`select * from person where a=${1} and b=${new Date()}`;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    In DiscussionNot yet reached consensusSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions